2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-20 16:52:13 +00:00

3 Commits

Author SHA1 Message Date
Zach Laine
20b017c965 Generated by Github action on push to master. 2024-01-18 06:56:05 +00:00
Zach Laine
c4d9e4fbcd Generated by Github action on push to master. 2024-01-18 06:27:48 +00:00
Zach Laine
c68897b9e6 Replace all the headers with a generated, unified header. 2024-01-17 23:52:18 -06:00
45 changed files with 26333 additions and 27706 deletions

View File

@@ -1,99 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_CONCEPTS_HPP
#define BOOST_PARSER_CONCEPTS_HPP
#include <boost/parser/config.hpp>
#include <boost/parser/parser_fwd.hpp>
#include <boost/parser/detail/text/transcode_view.hpp>
#if defined(BOOST_PARSER_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS
#include <ranges>
namespace boost { namespace parser {
//[ all_concepts
template<typename T>
concept parsable_code_unit =
std::same_as<std::remove_cv_t<T>, char> ||
std::same_as<std::remove_cv_t<T>, wchar_t> ||
std::same_as<std::remove_cv_t<T>, char8_t> ||
std::same_as<std::remove_cv_t<T>, char16_t>||
std::same_as<std::remove_cv_t<T>, char32_t>;
template<typename T>
concept parsable_iter =
std::forward_iterator<T> && parsable_code_unit<std::iter_value_t<T>>;
//[ parsable_range_like_concept
template<typename T>
concept parsable_range = std::ranges::forward_range<T> &&
parsable_code_unit<std::ranges::range_value_t<T>>;
template<typename T>
concept parsable_pointer = std::is_pointer_v<std::remove_cvref_t<T>> &&
parsable_code_unit<std::remove_pointer_t<std::remove_cvref_t<T>>>;
template<typename T>
concept parsable_range_like = parsable_range<T> || parsable_pointer<T>;
//]
template<
typename I,
typename S,
typename ErrorHandler,
typename GlobalState>
using minimal_parse_context = decltype(detail::make_context(
std::declval<I>(),
std::declval<S>(),
std::declval<bool &>(),
std::declval<int &>(),
std::declval<ErrorHandler const &>(),
std::declval<detail::nope &>(),
std::declval<detail::symbol_table_tries_t &>()));
template<typename T, typename I, typename S, typename GlobalState>
concept error_handler =
requires (
T const & t,
I first,
S last,
parse_error<I> const & e,
diagnostic_kind kind,
std::string_view message,
minimal_parse_context<
I, S, T, GlobalState> const & context) {
{ t(first, last, e) } -> std::same_as<error_handler_result>;
t.diagnose(kind, message, context, first);
t.diagnose(kind, message, context);
};
//[ container_concept
template<typename T>
concept container = std::ranges::common_range<T> && requires(T t) {
{ t.insert(t.begin(), *t.begin()) }
-> std::same_as<std::ranges::iterator_t<T>>;
};
//]
//]
namespace detail {
template<typename T, typename U>
concept container_and_value_type = container<T> &&
(std::is_same_v<std::ranges::range_value_t<T>, U> ||
(std::is_same_v<T, std::string> && std::is_same_v<U, char32_t>));
}
}}
#endif
#endif

View File

@@ -1,95 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_CONFIG_HPP
#define BOOST_PARSER_CONFIG_HPP
#include <boost/parser/detail/debug_assert.hpp>
// Included for definition of __cpp_lib_concepts.
#include <iterator>
#ifdef BOOST_PARSER_DOXYGEN
/** Boost.Parser uses assertions (`BOOST_ASSERT()`) in several places to
indicate that your use of the library has an error in it. All of those
places could heve instead been ill-formed code, caught at compile time.
It is far quicker and easier to determine exactly where in your code such
an error is located if this is a runtime failure; you can just look at the
stack in your favorite debugger. However, if you want to make thes kinds
of errors always ill-formed code, define this macro. */
# define BOOST_PARSER_NO_RUNTIME_ASSERTIONS
/** Asserts that the given condition is true. If
`BOOST_PARSER_NO_RUNTIME_ASSERTIONS` macro is defined by the user,
`BOOST_PARSER_ASSERT` expends to a compile-time `static_assert()`.
Otherwise, it expands to a run-time `BOOST_ASSERT()`. */
# define BOOST_PARSER_ASSERT(condition)
/** Boost.Parser will automatically use concepts to constrain templates when
building in C++20 mode, if the compiler defines `__cpp_lib_concepts`. To
disable the use of concepts, define this macro. */
# define BOOST_PARSER_DISABLE_CONCEPTS
/** Define this macro to use `std::tuple` instead of `boost::hana::tuple`
throughout Boost.Parser. */
# define BOOST_PARSER_DISABLE_HANA_TUPLE
/** Boost.Parser automatically treats aggregate structs as if they were
tuples. It uses some metaprogramming to do this. The technique used has
a hard limit on the number of data members a struct can have. Re-define
this macro to change the hard limit. Note that large values may increase
compile times. */
# define BOOST_PARSER_MAX_AGGREGATE_SIZE 25
/** The subrange template that is used throughout Boost.Parser. This will be
`boost::parser::subrange` in C++17 builds, and `std::ranges::subrange` in
all other builds. */
# define BOOST_PARSER_SUBRANGE
#else
# ifdef BOOST_PARSER_NO_RUNTIME_ASSERTIONS
# define BOOST_PARSER_ASSERT(condition) static_assert(condition)
# elif defined(BOOST_PARSER_HAVE_BOOST_ASSERT)
# define BOOST_PARSER_ASSERT(condition) BOOST_ASSERT(condition)
# else
# define BOOST_PARSER_ASSERT(condition) assert(condition)
# endif
#endif
#if defined(__cpp_lib_concepts) && !defined(BOOST_PARSER_DISABLE_CONCEPTS)
# define BOOST_PARSER_USE_CONCEPTS 1
#else
# define BOOST_PARSER_USE_CONCEPTS 0
#endif
#if defined(__cpp_lib_ranges)
# define BOOST_PARSER_SUBRANGE std::ranges::subrange
#else
# include <boost/parser/subrange.hpp>
# define BOOST_PARSER_SUBRANGE boost::parser::subrange
#endif
#if defined(BOOST_PARSER_DISABLE_HANA_TUPLE)
# define BOOST_PARSER_USE_STD_TUPLE 1
#else
# define BOOST_PARSER_USE_STD_TUPLE 0
#endif
#if !defined(BOOST_PARSER_MAX_AGGREGATE_SIZE)
#define BOOST_PARSER_MAX_AGGREGATE_SIZE 25
#endif
// VS2019 and VS2017 need conditional constexpr in some places, even in C++17 mode.
#if !defined(_MSC_VER) || 1930 <= _MSC_VER
#define BOOST_PARSER_CONSTEXPR constexpr
#else
#define BOOST_PARSER_CONSTEXPR
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,112 +0,0 @@
#ifndef BOOST_PARSER_DETAIL_CASE_FOLD_HPP
#define BOOST_PARSER_DETAIL_CASE_FOLD_HPP
#include <boost/parser/config.hpp>
#include <boost/parser/detail/text/transcode_iterator.hpp>
#include <boost/parser/detail/case_fold_data_generated.hpp>
#include <algorithm>
namespace boost::parser::detail {
template<typename I>
std::optional<I> do_short_mapping(
short_mapping_range const * first,
short_mapping_range const * last,
char32_t cp,
I out)
{
auto it = std::lower_bound(
first,
last,
cp,
[](short_mapping_range const & range, char32_t cp) {
return range.cp_first_ < cp;
});
if (it != first) {
auto const prev = it - 1;
if (prev->cp_first_ <= cp && cp < prev->cp_last_)
it = prev;
}
if (it != last && it->cp_first_ <= cp && cp < it->cp_last_) {
auto const offset = cp - it->cp_first_;
if (offset % it->stride_ == 0) {
*out++ =
single_mapping_cps[it->first_idx_ + offset / it->stride_];
return out;
}
}
return std::nullopt;
}
template<typename I>
I case_fold(char32_t cp, I out)
{
// One-byte fast path.
if (cp < 0x100) {
// ASCII letter fast path.
if (0x41 <= cp && cp < 0x5a) {
*out++ = cp + 0x20;
return out;
} else if (cp == 0x00DF) {
// The lone multi-mapping below 0x100.
*out++ = 0x0073;
*out++ = 0x0073;
return out;
} else {
// Skip [0x41, 0x5a), handled above.
auto const first =
detail::text::detail::begin(mapping_ranges) + 1;
// 7th entry starts with 0x100.
auto const last =
detail::text::detail::begin(mapping_ranges) + 7;
if (auto out_opt = do_short_mapping(first, last, cp, out))
return *out_opt;
}
*out++ = cp;
return out;
}
// Single-cp-mapping path (next most common case).
{
auto const first = detail::text::detail::begin(mapping_ranges);
auto const last = detail::text::detail::end(mapping_ranges);
if (auto out_opt = do_short_mapping(first, last, cp, out))
return *out_opt;
}
// Multi-cp mapping path.
{
auto const last = detail::text::detail::end(long_mappings);
auto const it = std::lower_bound(
detail::text::detail::begin(long_mappings),
last,
cp,
[](long_mapping const & mapping, char32_t cp) {
return mapping.cp_ < cp;
});
if (it != last && it->cp_ == cp) {
#if BOOST_PARSER_USE_CONCEPTS
return std::ranges::copy(it->mapping_, text::null_sentinel, out)
.out;
#else
return std::copy(
it->mapping_,
std::find(
detail::text::detail::begin(it->mapping_),
detail::text::detail::end(it->mapping_),
0),
out);
#endif
}
}
*out++ = cp;
return out;
}
}
#endif

View File

@@ -1,533 +0,0 @@
// Copyright (c) 2024 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Warning: This header is auto-generated (see misc/generate_case_fold_data.py).
// The lack of include guards is intentional.
namespace boost::parser::detail {
struct short_mapping_range {
char32_t cp_first_;
char32_t cp_last_;
uint16_t stride_;
uint16_t first_idx_;
};
inline constexpr int longest_mapping = 3;
struct long_mapping {
char32_t cp_;
char32_t mapping_[longest_mapping + 1];
};
inline constexpr long_mapping long_mappings[104] = {
{0x00DF, {0x0073, 0x0073 , 0}},
{0x0130, {0x0069, 0x0307 , 0}},
{0x0149, {0x02BC, 0x006E , 0}},
{0x01F0, {0x006A, 0x030C , 0}},
{0x0390, {0x03B9, 0x0308, 0x0301 , 0}},
{0x03B0, {0x03C5, 0x0308, 0x0301 , 0}},
{0x0587, {0x0565, 0x0582 , 0}},
{0x1E96, {0x0068, 0x0331 , 0}},
{0x1E97, {0x0074, 0x0308 , 0}},
{0x1E98, {0x0077, 0x030A , 0}},
{0x1E99, {0x0079, 0x030A , 0}},
{0x1E9A, {0x0061, 0x02BE , 0}},
{0x1E9E, {0x0073, 0x0073 , 0}},
{0x1F50, {0x03C5, 0x0313 , 0}},
{0x1F52, {0x03C5, 0x0313, 0x0300 , 0}},
{0x1F54, {0x03C5, 0x0313, 0x0301 , 0}},
{0x1F56, {0x03C5, 0x0313, 0x0342 , 0}},
{0x1F80, {0x1F00, 0x03B9 , 0}},
{0x1F81, {0x1F01, 0x03B9 , 0}},
{0x1F82, {0x1F02, 0x03B9 , 0}},
{0x1F83, {0x1F03, 0x03B9 , 0}},
{0x1F84, {0x1F04, 0x03B9 , 0}},
{0x1F85, {0x1F05, 0x03B9 , 0}},
{0x1F86, {0x1F06, 0x03B9 , 0}},
{0x1F87, {0x1F07, 0x03B9 , 0}},
{0x1F88, {0x1F00, 0x03B9 , 0}},
{0x1F89, {0x1F01, 0x03B9 , 0}},
{0x1F8A, {0x1F02, 0x03B9 , 0}},
{0x1F8B, {0x1F03, 0x03B9 , 0}},
{0x1F8C, {0x1F04, 0x03B9 , 0}},
{0x1F8D, {0x1F05, 0x03B9 , 0}},
{0x1F8E, {0x1F06, 0x03B9 , 0}},
{0x1F8F, {0x1F07, 0x03B9 , 0}},
{0x1F90, {0x1F20, 0x03B9 , 0}},
{0x1F91, {0x1F21, 0x03B9 , 0}},
{0x1F92, {0x1F22, 0x03B9 , 0}},
{0x1F93, {0x1F23, 0x03B9 , 0}},
{0x1F94, {0x1F24, 0x03B9 , 0}},
{0x1F95, {0x1F25, 0x03B9 , 0}},
{0x1F96, {0x1F26, 0x03B9 , 0}},
{0x1F97, {0x1F27, 0x03B9 , 0}},
{0x1F98, {0x1F20, 0x03B9 , 0}},
{0x1F99, {0x1F21, 0x03B9 , 0}},
{0x1F9A, {0x1F22, 0x03B9 , 0}},
{0x1F9B, {0x1F23, 0x03B9 , 0}},
{0x1F9C, {0x1F24, 0x03B9 , 0}},
{0x1F9D, {0x1F25, 0x03B9 , 0}},
{0x1F9E, {0x1F26, 0x03B9 , 0}},
{0x1F9F, {0x1F27, 0x03B9 , 0}},
{0x1FA0, {0x1F60, 0x03B9 , 0}},
{0x1FA1, {0x1F61, 0x03B9 , 0}},
{0x1FA2, {0x1F62, 0x03B9 , 0}},
{0x1FA3, {0x1F63, 0x03B9 , 0}},
{0x1FA4, {0x1F64, 0x03B9 , 0}},
{0x1FA5, {0x1F65, 0x03B9 , 0}},
{0x1FA6, {0x1F66, 0x03B9 , 0}},
{0x1FA7, {0x1F67, 0x03B9 , 0}},
{0x1FA8, {0x1F60, 0x03B9 , 0}},
{0x1FA9, {0x1F61, 0x03B9 , 0}},
{0x1FAA, {0x1F62, 0x03B9 , 0}},
{0x1FAB, {0x1F63, 0x03B9 , 0}},
{0x1FAC, {0x1F64, 0x03B9 , 0}},
{0x1FAD, {0x1F65, 0x03B9 , 0}},
{0x1FAE, {0x1F66, 0x03B9 , 0}},
{0x1FAF, {0x1F67, 0x03B9 , 0}},
{0x1FB2, {0x1F70, 0x03B9 , 0}},
{0x1FB3, {0x03B1, 0x03B9 , 0}},
{0x1FB4, {0x03AC, 0x03B9 , 0}},
{0x1FB6, {0x03B1, 0x0342 , 0}},
{0x1FB7, {0x03B1, 0x0342, 0x03B9 , 0}},
{0x1FBC, {0x03B1, 0x03B9 , 0}},
{0x1FC2, {0x1F74, 0x03B9 , 0}},
{0x1FC3, {0x03B7, 0x03B9 , 0}},
{0x1FC4, {0x03AE, 0x03B9 , 0}},
{0x1FC6, {0x03B7, 0x0342 , 0}},
{0x1FC7, {0x03B7, 0x0342, 0x03B9 , 0}},
{0x1FCC, {0x03B7, 0x03B9 , 0}},
{0x1FD2, {0x03B9, 0x0308, 0x0300 , 0}},
{0x1FD3, {0x03B9, 0x0308, 0x0301 , 0}},
{0x1FD6, {0x03B9, 0x0342 , 0}},
{0x1FD7, {0x03B9, 0x0308, 0x0342 , 0}},
{0x1FE2, {0x03C5, 0x0308, 0x0300 , 0}},
{0x1FE3, {0x03C5, 0x0308, 0x0301 , 0}},
{0x1FE4, {0x03C1, 0x0313 , 0}},
{0x1FE6, {0x03C5, 0x0342 , 0}},
{0x1FE7, {0x03C5, 0x0308, 0x0342 , 0}},
{0x1FF2, {0x1F7C, 0x03B9 , 0}},
{0x1FF3, {0x03C9, 0x03B9 , 0}},
{0x1FF4, {0x03CE, 0x03B9 , 0}},
{0x1FF6, {0x03C9, 0x0342 , 0}},
{0x1FF7, {0x03C9, 0x0342, 0x03B9 , 0}},
{0x1FFC, {0x03C9, 0x03B9 , 0}},
{0xFB00, {0x0066, 0x0066 , 0}},
{0xFB01, {0x0066, 0x0069 , 0}},
{0xFB02, {0x0066, 0x006C , 0}},
{0xFB03, {0x0066, 0x0066, 0x0069 , 0}},
{0xFB04, {0x0066, 0x0066, 0x006C , 0}},
{0xFB05, {0x0073, 0x0074 , 0}},
{0xFB06, {0x0073, 0x0074 , 0}},
{0xFB13, {0x0574, 0x0576 , 0}},
{0xFB14, {0x0574, 0x0565 , 0}},
{0xFB15, {0x0574, 0x056B , 0}},
{0xFB16, {0x057E, 0x0576 , 0}},
{0xFB17, {0x0574, 0x056D , 0}},
};
inline constexpr short_mapping_range mapping_ranges[220] = {
{0x0041, 0x005A, 1, 0},
{0x005A, 0x00B5, 91, 25},
{0x00B5, 0x00C0, 11, 26},
{0x00C0, 0x00D6, 1, 27},
{0x00D6, 0x00D8, 2, 49},
{0x00D8, 0x00DE, 1, 50},
{0x00DE, 0x0100, 34, 56},
{0x0100, 0x012E, 2, 57},
{0x012E, 0x0132, 4, 80},
{0x0132, 0x0136, 2, 81},
{0x0136, 0x0139, 3, 83},
{0x0139, 0x0147, 2, 84},
{0x0147, 0x014A, 3, 91},
{0x014A, 0x0178, 2, 92},
{0x0178, 0x0179, 1, 115},
{0x0179, 0x0181, 2, 116},
{0x0181, 0x0182, 1, 120},
{0x0182, 0x0186, 2, 121},
{0x0186, 0x0187, 1, 123},
{0x0187, 0x0189, 2, 124},
{0x0189, 0x018B, 1, 125},
{0x018B, 0x018E, 3, 127},
{0x018E, 0x0191, 1, 128},
{0x0191, 0x0193, 2, 131},
{0x0193, 0x0194, 1, 132},
{0x0194, 0x0196, 2, 133},
{0x0196, 0x0198, 1, 134},
{0x0198, 0x019C, 4, 136},
{0x019C, 0x019D, 1, 137},
{0x019D, 0x019F, 2, 138},
{0x019F, 0x01A0, 1, 139},
{0x01A0, 0x01A6, 2, 140},
{0x01A6, 0x01A7, 1, 143},
{0x01A7, 0x01A9, 2, 144},
{0x01A9, 0x01AC, 3, 145},
{0x01AC, 0x01AE, 2, 146},
{0x01AE, 0x01AF, 1, 147},
{0x01AF, 0x01B1, 2, 148},
{0x01B1, 0x01B3, 1, 149},
{0x01B3, 0x01B7, 2, 151},
{0x01B7, 0x01B8, 1, 153},
{0x01B8, 0x01BC, 4, 154},
{0x01BC, 0x01C4, 8, 155},
{0x01C4, 0x01C5, 1, 156},
{0x01C5, 0x01C7, 2, 157},
{0x01C7, 0x01C8, 1, 158},
{0x01C8, 0x01CA, 2, 159},
{0x01CA, 0x01CB, 1, 160},
{0x01CB, 0x01DB, 2, 161},
{0x01DB, 0x01DE, 3, 169},
{0x01DE, 0x01EE, 2, 170},
{0x01EE, 0x01F1, 3, 178},
{0x01F1, 0x01F2, 1, 179},
{0x01F2, 0x01F6, 2, 180},
{0x01F6, 0x01F8, 1, 182},
{0x01F8, 0x0232, 2, 184},
{0x0232, 0x023A, 8, 213},
{0x023A, 0x023B, 1, 214},
{0x023B, 0x023D, 2, 215},
{0x023D, 0x023E, 1, 216},
{0x023E, 0x0241, 3, 217},
{0x0241, 0x0243, 2, 218},
{0x0243, 0x0246, 1, 219},
{0x0246, 0x024E, 2, 222},
{0x024E, 0x0345, 247, 226},
{0x0345, 0x0370, 43, 227},
{0x0370, 0x0372, 2, 228},
{0x0372, 0x0376, 4, 229},
{0x0376, 0x037F, 9, 230},
{0x037F, 0x0386, 7, 231},
{0x0386, 0x0388, 2, 232},
{0x0388, 0x038A, 1, 233},
{0x038A, 0x038E, 2, 235},
{0x038E, 0x038F, 1, 237},
{0x038F, 0x0391, 2, 238},
{0x0391, 0x03A1, 1, 239},
{0x03A1, 0x03A3, 2, 255},
{0x03A3, 0x03AB, 1, 256},
{0x03AB, 0x03C2, 23, 264},
{0x03C2, 0x03CF, 13, 265},
{0x03CF, 0x03D1, 1, 266},
{0x03D1, 0x03D5, 4, 268},
{0x03D5, 0x03D6, 1, 269},
{0x03D6, 0x03F0, 2, 270},
{0x03F0, 0x03F1, 1, 283},
{0x03F1, 0x03F4, 3, 284},
{0x03F4, 0x03F5, 1, 285},
{0x03F5, 0x03F9, 2, 286},
{0x03F9, 0x03FA, 1, 288},
{0x03FA, 0x03FD, 3, 289},
{0x03FD, 0x042F, 1, 290},
{0x042F, 0x0460, 49, 340},
{0x0460, 0x0480, 2, 341},
{0x0480, 0x048A, 10, 357},
{0x048A, 0x04C0, 2, 358},
{0x04C0, 0x04C1, 1, 385},
{0x04C1, 0x04CD, 2, 386},
{0x04CD, 0x04D0, 3, 392},
{0x04D0, 0x052E, 2, 393},
{0x052E, 0x0531, 3, 440},
{0x0531, 0x0556, 1, 441},
{0x0556, 0x10A0, 2890, 478},
{0x10A0, 0x10C5, 1, 479},
{0x10C5, 0x10C7, 2, 516},
{0x10C7, 0x10CD, 6, 517},
{0x10CD, 0x13F8, 811, 518},
{0x13F8, 0x13FD, 1, 519},
{0x13FD, 0x1C80, 2179, 524},
{0x1C80, 0x1C88, 1, 525},
{0x1C88, 0x1C90, 8, 533},
{0x1C90, 0x1CBA, 1, 534},
{0x1CBA, 0x1CBD, 3, 576},
{0x1CBD, 0x1CBF, 1, 577},
{0x1CBF, 0x1E00, 321, 579},
{0x1E00, 0x1E94, 2, 580},
{0x1E94, 0x1E9B, 7, 654},
{0x1E9B, 0x1EA0, 5, 655},
{0x1EA0, 0x1EFE, 2, 656},
{0x1EFE, 0x1F08, 10, 703},
{0x1F08, 0x1F0F, 1, 704},
{0x1F0F, 0x1F18, 9, 711},
{0x1F18, 0x1F1D, 1, 712},
{0x1F1D, 0x1F28, 11, 717},
{0x1F28, 0x1F2F, 1, 718},
{0x1F2F, 0x1F38, 9, 725},
{0x1F38, 0x1F3F, 1, 726},
{0x1F3F, 0x1F48, 9, 733},
{0x1F48, 0x1F4D, 1, 734},
{0x1F4D, 0x1F59, 12, 739},
{0x1F59, 0x1F5F, 2, 740},
{0x1F5F, 0x1F68, 9, 743},
{0x1F68, 0x1F6F, 1, 744},
{0x1F6F, 0x1FB8, 73, 751},
{0x1FB8, 0x1FBB, 1, 752},
{0x1FBB, 0x1FBE, 3, 755},
{0x1FBE, 0x1FC8, 10, 756},
{0x1FC8, 0x1FCB, 1, 757},
{0x1FCB, 0x1FD8, 13, 760},
{0x1FD8, 0x1FDB, 1, 761},
{0x1FDB, 0x1FE8, 13, 764},
{0x1FE8, 0x1FEC, 1, 765},
{0x1FEC, 0x1FF8, 12, 769},
{0x1FF8, 0x1FFB, 1, 770},
{0x1FFB, 0x2126, 299, 773},
{0x2126, 0x212A, 4, 774},
{0x212A, 0x212B, 1, 775},
{0x212B, 0x2132, 7, 776},
{0x2132, 0x2160, 46, 777},
{0x2160, 0x216F, 1, 778},
{0x216F, 0x2183, 20, 793},
{0x2183, 0x24B6, 819, 794},
{0x24B6, 0x24CF, 1, 795},
{0x24CF, 0x2C00, 1841, 820},
{0x2C00, 0x2C2F, 1, 821},
{0x2C2F, 0x2C60, 49, 868},
{0x2C60, 0x2C62, 2, 869},
{0x2C62, 0x2C64, 1, 870},
{0x2C64, 0x2C67, 3, 872},
{0x2C67, 0x2C6D, 2, 873},
{0x2C6D, 0x2C70, 1, 876},
{0x2C70, 0x2C72, 2, 879},
{0x2C72, 0x2C75, 3, 880},
{0x2C75, 0x2C7E, 9, 881},
{0x2C7E, 0x2C80, 1, 882},
{0x2C80, 0x2CE2, 2, 884},
{0x2CE2, 0x2CEB, 9, 933},
{0x2CEB, 0x2CED, 2, 934},
{0x2CED, 0x2CF2, 5, 935},
{0x2CF2, 0xA640, 31054, 936},
{0xA640, 0xA66C, 2, 937},
{0xA66C, 0xA680, 20, 959},
{0xA680, 0xA69A, 2, 960},
{0xA69A, 0xA722, 136, 973},
{0xA722, 0xA72E, 2, 974},
{0xA72E, 0xA732, 4, 980},
{0xA732, 0xA76E, 2, 981},
{0xA76E, 0xA779, 11, 1011},
{0xA779, 0xA77D, 2, 1012},
{0xA77D, 0xA77E, 1, 1014},
{0xA77E, 0xA786, 2, 1015},
{0xA786, 0xA78B, 5, 1019},
{0xA78B, 0xA78D, 2, 1020},
{0xA78D, 0xA790, 3, 1021},
{0xA790, 0xA792, 2, 1022},
{0xA792, 0xA796, 4, 1023},
{0xA796, 0xA7AA, 2, 1024},
{0xA7AA, 0xA7AE, 1, 1034},
{0xA7AE, 0xA7B0, 2, 1038},
{0xA7B0, 0xA7B4, 1, 1039},
{0xA7B4, 0xA7C4, 2, 1043},
{0xA7C4, 0xA7C7, 1, 1051},
{0xA7C7, 0xA7C9, 2, 1054},
{0xA7C9, 0xA7D0, 7, 1055},
{0xA7D0, 0xA7D6, 6, 1056},
{0xA7D6, 0xA7D8, 2, 1057},
{0xA7D8, 0xA7F5, 29, 1058},
{0xA7F5, 0xAB70, 891, 1059},
{0xAB70, 0xABBF, 1, 1060},
{0xABBF, 0xFF21, 21346, 1139},
{0xFF21, 0xFF3A, 1, 1140},
{0xFF3A, 0x10400, 1222, 1165},
{0x10400, 0x10427, 1, 1166},
{0x10427, 0x104B0, 137, 1205},
{0x104B0, 0x104D3, 1, 1206},
{0x104D3, 0x10570, 157, 1241},
{0x10570, 0x1057A, 1, 1242},
{0x1057A, 0x1057C, 2, 1252},
{0x1057C, 0x1058A, 1, 1253},
{0x1058A, 0x1058C, 2, 1267},
{0x1058C, 0x10592, 1, 1268},
{0x10592, 0x10594, 2, 1274},
{0x10594, 0x10595, 1, 1275},
{0x10595, 0x10C80, 1771, 1276},
{0x10C80, 0x10CB2, 1, 1277},
{0x10CB2, 0x118A0, 3054, 1327},
{0x118A0, 0x118BF, 1, 1328},
{0x118BF, 0x16E40, 21889, 1359},
{0x16E40, 0x16E5F, 1, 1360},
{0x16E5F, 0x1E900, 31393, 1391},
{0x1E900, 0x1E921 + 1, 1, 1392},
};
inline constexpr char32_t single_mapping_cps[1426] = {
0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068,
0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070,
0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
0x0079, 0x007A, 0x03BC, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4,
0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC,
0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4,
0x00F5, 0x00F6, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD,
0x00FE, 0x0101, 0x0103, 0x0105, 0x0107, 0x0109, 0x010B, 0x010D,
0x010F, 0x0111, 0x0113, 0x0115, 0x0117, 0x0119, 0x011B, 0x011D,
0x011F, 0x0121, 0x0123, 0x0125, 0x0127, 0x0129, 0x012B, 0x012D,
0x012F, 0x0133, 0x0135, 0x0137, 0x013A, 0x013C, 0x013E, 0x0140,
0x0142, 0x0144, 0x0146, 0x0148, 0x014B, 0x014D, 0x014F, 0x0151,
0x0153, 0x0155, 0x0157, 0x0159, 0x015B, 0x015D, 0x015F, 0x0161,
0x0163, 0x0165, 0x0167, 0x0169, 0x016B, 0x016D, 0x016F, 0x0171,
0x0173, 0x0175, 0x0177, 0x00FF, 0x017A, 0x017C, 0x017E, 0x0073,
0x0253, 0x0183, 0x0185, 0x0254, 0x0188, 0x0256, 0x0257, 0x018C,
0x01DD, 0x0259, 0x025B, 0x0192, 0x0260, 0x0263, 0x0269, 0x0268,
0x0199, 0x026F, 0x0272, 0x0275, 0x01A1, 0x01A3, 0x01A5, 0x0280,
0x01A8, 0x0283, 0x01AD, 0x0288, 0x01B0, 0x028A, 0x028B, 0x01B4,
0x01B6, 0x0292, 0x01B9, 0x01BD, 0x01C6, 0x01C6, 0x01C9, 0x01C9,
0x01CC, 0x01CC, 0x01CE, 0x01D0, 0x01D2, 0x01D4, 0x01D6, 0x01D8,
0x01DA, 0x01DC, 0x01DF, 0x01E1, 0x01E3, 0x01E5, 0x01E7, 0x01E9,
0x01EB, 0x01ED, 0x01EF, 0x01F3, 0x01F3, 0x01F5, 0x0195, 0x01BF,
0x01F9, 0x01FB, 0x01FD, 0x01FF, 0x0201, 0x0203, 0x0205, 0x0207,
0x0209, 0x020B, 0x020D, 0x020F, 0x0211, 0x0213, 0x0215, 0x0217,
0x0219, 0x021B, 0x021D, 0x021F, 0x019E, 0x0223, 0x0225, 0x0227,
0x0229, 0x022B, 0x022D, 0x022F, 0x0231, 0x0233, 0x2C65, 0x023C,
0x019A, 0x2C66, 0x0242, 0x0180, 0x0289, 0x028C, 0x0247, 0x0249,
0x024B, 0x024D, 0x024F, 0x03B9, 0x0371, 0x0373, 0x0377, 0x03F3,
0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03CC, 0x03CD, 0x03CE, 0x03B1,
0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9,
0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1,
0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA,
0x03CB, 0x03C3, 0x03D7, 0x03B2, 0x03B8, 0x03C6, 0x03C0, 0x03D9,
0x03DB, 0x03DD, 0x03DF, 0x03E1, 0x03E3, 0x03E5, 0x03E7, 0x03E9,
0x03EB, 0x03ED, 0x03EF, 0x03BA, 0x03C1, 0x03B8, 0x03B5, 0x03F8,
0x03F2, 0x03FB, 0x037B, 0x037C, 0x037D, 0x0450, 0x0451, 0x0452,
0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A,
0x045B, 0x045C, 0x045D, 0x045E, 0x045F, 0x0430, 0x0431, 0x0432,
0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A,
0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442,
0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A,
0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 0x0461, 0x0463, 0x0465,
0x0467, 0x0469, 0x046B, 0x046D, 0x046F, 0x0471, 0x0473, 0x0475,
0x0477, 0x0479, 0x047B, 0x047D, 0x047F, 0x0481, 0x048B, 0x048D,
0x048F, 0x0491, 0x0493, 0x0495, 0x0497, 0x0499, 0x049B, 0x049D,
0x049F, 0x04A1, 0x04A3, 0x04A5, 0x04A7, 0x04A9, 0x04AB, 0x04AD,
0x04AF, 0x04B1, 0x04B3, 0x04B5, 0x04B7, 0x04B9, 0x04BB, 0x04BD,
0x04BF, 0x04CF, 0x04C2, 0x04C4, 0x04C6, 0x04C8, 0x04CA, 0x04CC,
0x04CE, 0x04D1, 0x04D3, 0x04D5, 0x04D7, 0x04D9, 0x04DB, 0x04DD,
0x04DF, 0x04E1, 0x04E3, 0x04E5, 0x04E7, 0x04E9, 0x04EB, 0x04ED,
0x04EF, 0x04F1, 0x04F3, 0x04F5, 0x04F7, 0x04F9, 0x04FB, 0x04FD,
0x04FF, 0x0501, 0x0503, 0x0505, 0x0507, 0x0509, 0x050B, 0x050D,
0x050F, 0x0511, 0x0513, 0x0515, 0x0517, 0x0519, 0x051B, 0x051D,
0x051F, 0x0521, 0x0523, 0x0525, 0x0527, 0x0529, 0x052B, 0x052D,
0x052F, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x2D00,
0x2D01, 0x2D02, 0x2D03, 0x2D04, 0x2D05, 0x2D06, 0x2D07, 0x2D08,
0x2D09, 0x2D0A, 0x2D0B, 0x2D0C, 0x2D0D, 0x2D0E, 0x2D0F, 0x2D10,
0x2D11, 0x2D12, 0x2D13, 0x2D14, 0x2D15, 0x2D16, 0x2D17, 0x2D18,
0x2D19, 0x2D1A, 0x2D1B, 0x2D1C, 0x2D1D, 0x2D1E, 0x2D1F, 0x2D20,
0x2D21, 0x2D22, 0x2D23, 0x2D24, 0x2D25, 0x2D27, 0x2D2D, 0x13F0,
0x13F1, 0x13F2, 0x13F3, 0x13F4, 0x13F5, 0x0432, 0x0434, 0x043E,
0x0441, 0x0442, 0x0442, 0x044A, 0x0463, 0xA64B, 0x10D0, 0x10D1,
0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, 0x10D8, 0x10D9,
0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, 0x10E0, 0x10E1,
0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8, 0x10E9,
0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, 0x10F0, 0x10F1,
0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7, 0x10F8, 0x10F9,
0x10FA, 0x10FD, 0x10FE, 0x10FF, 0x1E01, 0x1E03, 0x1E05, 0x1E07,
0x1E09, 0x1E0B, 0x1E0D, 0x1E0F, 0x1E11, 0x1E13, 0x1E15, 0x1E17,
0x1E19, 0x1E1B, 0x1E1D, 0x1E1F, 0x1E21, 0x1E23, 0x1E25, 0x1E27,
0x1E29, 0x1E2B, 0x1E2D, 0x1E2F, 0x1E31, 0x1E33, 0x1E35, 0x1E37,
0x1E39, 0x1E3B, 0x1E3D, 0x1E3F, 0x1E41, 0x1E43, 0x1E45, 0x1E47,
0x1E49, 0x1E4B, 0x1E4D, 0x1E4F, 0x1E51, 0x1E53, 0x1E55, 0x1E57,
0x1E59, 0x1E5B, 0x1E5D, 0x1E5F, 0x1E61, 0x1E63, 0x1E65, 0x1E67,
0x1E69, 0x1E6B, 0x1E6D, 0x1E6F, 0x1E71, 0x1E73, 0x1E75, 0x1E77,
0x1E79, 0x1E7B, 0x1E7D, 0x1E7F, 0x1E81, 0x1E83, 0x1E85, 0x1E87,
0x1E89, 0x1E8B, 0x1E8D, 0x1E8F, 0x1E91, 0x1E93, 0x1E95, 0x1E61,
0x1EA1, 0x1EA3, 0x1EA5, 0x1EA7, 0x1EA9, 0x1EAB, 0x1EAD, 0x1EAF,
0x1EB1, 0x1EB3, 0x1EB5, 0x1EB7, 0x1EB9, 0x1EBB, 0x1EBD, 0x1EBF,
0x1EC1, 0x1EC3, 0x1EC5, 0x1EC7, 0x1EC9, 0x1ECB, 0x1ECD, 0x1ECF,
0x1ED1, 0x1ED3, 0x1ED5, 0x1ED7, 0x1ED9, 0x1EDB, 0x1EDD, 0x1EDF,
0x1EE1, 0x1EE3, 0x1EE5, 0x1EE7, 0x1EE9, 0x1EEB, 0x1EED, 0x1EEF,
0x1EF1, 0x1EF3, 0x1EF5, 0x1EF7, 0x1EF9, 0x1EFB, 0x1EFD, 0x1EFF,
0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F20, 0x1F21,
0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, 0x1F30, 0x1F31,
0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, 0x1F40, 0x1F41,
0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F51, 0x1F53, 0x1F55, 0x1F57,
0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x03B9, 0x1F72, 0x1F73, 0x1F74,
0x1F75, 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x1FE0, 0x1FE1, 0x1F7A,
0x1F7B, 0x1FE5, 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x03C9, 0x006B,
0x00E5, 0x214E, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175,
0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D,
0x217E, 0x217F, 0x2184, 0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4,
0x24D5, 0x24D6, 0x24D7, 0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC,
0x24DD, 0x24DE, 0x24DF, 0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4,
0x24E5, 0x24E6, 0x24E7, 0x24E8, 0x24E9, 0x2C30, 0x2C31, 0x2C32,
0x2C33, 0x2C34, 0x2C35, 0x2C36, 0x2C37, 0x2C38, 0x2C39, 0x2C3A,
0x2C3B, 0x2C3C, 0x2C3D, 0x2C3E, 0x2C3F, 0x2C40, 0x2C41, 0x2C42,
0x2C43, 0x2C44, 0x2C45, 0x2C46, 0x2C47, 0x2C48, 0x2C49, 0x2C4A,
0x2C4B, 0x2C4C, 0x2C4D, 0x2C4E, 0x2C4F, 0x2C50, 0x2C51, 0x2C52,
0x2C53, 0x2C54, 0x2C55, 0x2C56, 0x2C57, 0x2C58, 0x2C59, 0x2C5A,
0x2C5B, 0x2C5C, 0x2C5D, 0x2C5E, 0x2C5F, 0x2C61, 0x026B, 0x1D7D,
0x027D, 0x2C68, 0x2C6A, 0x2C6C, 0x0251, 0x0271, 0x0250, 0x0252,
0x2C73, 0x2C76, 0x023F, 0x0240, 0x2C81, 0x2C83, 0x2C85, 0x2C87,
0x2C89, 0x2C8B, 0x2C8D, 0x2C8F, 0x2C91, 0x2C93, 0x2C95, 0x2C97,
0x2C99, 0x2C9B, 0x2C9D, 0x2C9F, 0x2CA1, 0x2CA3, 0x2CA5, 0x2CA7,
0x2CA9, 0x2CAB, 0x2CAD, 0x2CAF, 0x2CB1, 0x2CB3, 0x2CB5, 0x2CB7,
0x2CB9, 0x2CBB, 0x2CBD, 0x2CBF, 0x2CC1, 0x2CC3, 0x2CC5, 0x2CC7,
0x2CC9, 0x2CCB, 0x2CCD, 0x2CCF, 0x2CD1, 0x2CD3, 0x2CD5, 0x2CD7,
0x2CD9, 0x2CDB, 0x2CDD, 0x2CDF, 0x2CE1, 0x2CE3, 0x2CEC, 0x2CEE,
0x2CF3, 0xA641, 0xA643, 0xA645, 0xA647, 0xA649, 0xA64B, 0xA64D,
0xA64F, 0xA651, 0xA653, 0xA655, 0xA657, 0xA659, 0xA65B, 0xA65D,
0xA65F, 0xA661, 0xA663, 0xA665, 0xA667, 0xA669, 0xA66B, 0xA66D,
0xA681, 0xA683, 0xA685, 0xA687, 0xA689, 0xA68B, 0xA68D, 0xA68F,
0xA691, 0xA693, 0xA695, 0xA697, 0xA699, 0xA69B, 0xA723, 0xA725,
0xA727, 0xA729, 0xA72B, 0xA72D, 0xA72F, 0xA733, 0xA735, 0xA737,
0xA739, 0xA73B, 0xA73D, 0xA73F, 0xA741, 0xA743, 0xA745, 0xA747,
0xA749, 0xA74B, 0xA74D, 0xA74F, 0xA751, 0xA753, 0xA755, 0xA757,
0xA759, 0xA75B, 0xA75D, 0xA75F, 0xA761, 0xA763, 0xA765, 0xA767,
0xA769, 0xA76B, 0xA76D, 0xA76F, 0xA77A, 0xA77C, 0x1D79, 0xA77F,
0xA781, 0xA783, 0xA785, 0xA787, 0xA78C, 0x0265, 0xA791, 0xA793,
0xA797, 0xA799, 0xA79B, 0xA79D, 0xA79F, 0xA7A1, 0xA7A3, 0xA7A5,
0xA7A7, 0xA7A9, 0x0266, 0x025C, 0x0261, 0x026C, 0x026A, 0x029E,
0x0287, 0x029D, 0xAB53, 0xA7B5, 0xA7B7, 0xA7B9, 0xA7BB, 0xA7BD,
0xA7BF, 0xA7C1, 0xA7C3, 0xA794, 0x0282, 0x1D8E, 0xA7C8, 0xA7CA,
0xA7D1, 0xA7D7, 0xA7D9, 0xA7F6, 0x13A0, 0x13A1, 0x13A2, 0x13A3,
0x13A4, 0x13A5, 0x13A6, 0x13A7, 0x13A8, 0x13A9, 0x13AA, 0x13AB,
0x13AC, 0x13AD, 0x13AE, 0x13AF, 0x13B0, 0x13B1, 0x13B2, 0x13B3,
0x13B4, 0x13B5, 0x13B6, 0x13B7, 0x13B8, 0x13B9, 0x13BA, 0x13BB,
0x13BC, 0x13BD, 0x13BE, 0x13BF, 0x13C0, 0x13C1, 0x13C2, 0x13C3,
0x13C4, 0x13C5, 0x13C6, 0x13C7, 0x13C8, 0x13C9, 0x13CA, 0x13CB,
0x13CC, 0x13CD, 0x13CE, 0x13CF, 0x13D0, 0x13D1, 0x13D2, 0x13D3,
0x13D4, 0x13D5, 0x13D6, 0x13D7, 0x13D8, 0x13D9, 0x13DA, 0x13DB,
0x13DC, 0x13DD, 0x13DE, 0x13DF, 0x13E0, 0x13E1, 0x13E2, 0x13E3,
0x13E4, 0x13E5, 0x13E6, 0x13E7, 0x13E8, 0x13E9, 0x13EA, 0x13EB,
0x13EC, 0x13ED, 0x13EE, 0x13EF, 0xFF41, 0xFF42, 0xFF43, 0xFF44,
0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C,
0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54,
0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0x10428, 0x10429,
0x1042A, 0x1042B, 0x1042C, 0x1042D, 0x1042E, 0x1042F, 0x10430, 0x10431,
0x10432, 0x10433, 0x10434, 0x10435, 0x10436, 0x10437, 0x10438, 0x10439,
0x1043A, 0x1043B, 0x1043C, 0x1043D, 0x1043E, 0x1043F, 0x10440, 0x10441,
0x10442, 0x10443, 0x10444, 0x10445, 0x10446, 0x10447, 0x10448, 0x10449,
0x1044A, 0x1044B, 0x1044C, 0x1044D, 0x1044E, 0x1044F, 0x104D8, 0x104D9,
0x104DA, 0x104DB, 0x104DC, 0x104DD, 0x104DE, 0x104DF, 0x104E0, 0x104E1,
0x104E2, 0x104E3, 0x104E4, 0x104E5, 0x104E6, 0x104E7, 0x104E8, 0x104E9,
0x104EA, 0x104EB, 0x104EC, 0x104ED, 0x104EE, 0x104EF, 0x104F0, 0x104F1,
0x104F2, 0x104F3, 0x104F4, 0x104F5, 0x104F6, 0x104F7, 0x104F8, 0x104F9,
0x104FA, 0x104FB, 0x10597, 0x10598, 0x10599, 0x1059A, 0x1059B, 0x1059C,
0x1059D, 0x1059E, 0x1059F, 0x105A0, 0x105A1, 0x105A3, 0x105A4, 0x105A5,
0x105A6, 0x105A7, 0x105A8, 0x105A9, 0x105AA, 0x105AB, 0x105AC, 0x105AD,
0x105AE, 0x105AF, 0x105B0, 0x105B1, 0x105B3, 0x105B4, 0x105B5, 0x105B6,
0x105B7, 0x105B8, 0x105B9, 0x105BB, 0x105BC, 0x10CC0, 0x10CC1, 0x10CC2,
0x10CC3, 0x10CC4, 0x10CC5, 0x10CC6, 0x10CC7, 0x10CC8, 0x10CC9, 0x10CCA,
0x10CCB, 0x10CCC, 0x10CCD, 0x10CCE, 0x10CCF, 0x10CD0, 0x10CD1, 0x10CD2,
0x10CD3, 0x10CD4, 0x10CD5, 0x10CD6, 0x10CD7, 0x10CD8, 0x10CD9, 0x10CDA,
0x10CDB, 0x10CDC, 0x10CDD, 0x10CDE, 0x10CDF, 0x10CE0, 0x10CE1, 0x10CE2,
0x10CE3, 0x10CE4, 0x10CE5, 0x10CE6, 0x10CE7, 0x10CE8, 0x10CE9, 0x10CEA,
0x10CEB, 0x10CEC, 0x10CED, 0x10CEE, 0x10CEF, 0x10CF0, 0x10CF1, 0x10CF2,
0x118C0, 0x118C1, 0x118C2, 0x118C3, 0x118C4, 0x118C5, 0x118C6, 0x118C7,
0x118C8, 0x118C9, 0x118CA, 0x118CB, 0x118CC, 0x118CD, 0x118CE, 0x118CF,
0x118D0, 0x118D1, 0x118D2, 0x118D3, 0x118D4, 0x118D5, 0x118D6, 0x118D7,
0x118D8, 0x118D9, 0x118DA, 0x118DB, 0x118DC, 0x118DD, 0x118DE, 0x118DF,
0x16E60, 0x16E61, 0x16E62, 0x16E63, 0x16E64, 0x16E65, 0x16E66, 0x16E67,
0x16E68, 0x16E69, 0x16E6A, 0x16E6B, 0x16E6C, 0x16E6D, 0x16E6E, 0x16E6F,
0x16E70, 0x16E71, 0x16E72, 0x16E73, 0x16E74, 0x16E75, 0x16E76, 0x16E77,
0x16E78, 0x16E79, 0x16E7A, 0x16E7B, 0x16E7C, 0x16E7D, 0x16E7E, 0x16E7F,
0x1E922, 0x1E923, 0x1E924, 0x1E925, 0x1E926, 0x1E927, 0x1E928, 0x1E929,
0x1E92A, 0x1E92B, 0x1E92C, 0x1E92D, 0x1E92E, 0x1E92F, 0x1E930, 0x1E931,
0x1E932, 0x1E933, 0x1E934, 0x1E935, 0x1E936, 0x1E937, 0x1E938, 0x1E939,
0x1E93A, 0x1E93B, 0x1E93C, 0x1E93D, 0x1E93E, 0x1E93F, 0x1E940, 0x1E941,
0x1E942, 0x1E943,
};
}

View File

@@ -1,18 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_DEBUG_ASSERT_HPP
#define BOOST_PARSER_DETAIL_DEBUG_ASSERT_HPP
#if __has_include(<boost/assert.hpp>)
#include <boost/assert.hpp>
#define BOOST_PARSER_DEBUG_ASSERT(condition) BOOST_ASSERT(condition)
#define BOOST_PARSER_HAVE_BOOST_ASSERT
#else
#include <cassert>
#define BOOST_PARSER_DEBUG_ASSERT(condition) assert(condition)
#endif
#endif

View File

@@ -1,90 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_DETECTION_HPP
#define BOOST_PARSER_DETAIL_DETECTION_HPP
#include <type_traits>
namespace boost::parser::detail {
template<typename...>
struct void_
{
using type = void;
static constexpr bool value = true;
};
template<typename... T>
using void_t = typename void_<T...>::type;
template<typename T>
struct fixup_ptr
{
using type = T;
};
template<typename T>
using remove_v_t = typename std::remove_volatile<T>::type;
template<typename T>
struct fixup_ptr<T *>
{
using type = remove_v_t<T> const *;
};
template<typename T>
using fixup_ptr_t = typename fixup_ptr<T>::type;
template<typename T>
using remove_cv_ref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
struct nonesuch
{};
template<
typename Default,
typename AlwaysVoid,
template<typename...> class Template,
typename... Args>
struct detector
{
using value_t = std::false_type;
using type = Default;
};
template<
typename Default,
template<typename...> class Template,
typename... Args>
struct detector<Default, void_t<Template<Args...>>, Template, Args...>
{
using value_t = std::true_type;
using type = Template<Args...>;
};
template<template<typename...> class Template, typename... Args>
using is_detected =
typename detector<nonesuch, void, Template, Args...>::value_t;
template<template<typename...> class Template, typename... Args>
constexpr bool is_detected_v = is_detected<Template, Args...>::value;
template<template<typename...> class Template, typename... Args>
using detected_t =
typename detector<nonesuch, void, Template, Args...>::type;
template<
typename Default,
template<typename...> class Template,
typename... Args>
using detected_or_t =
typename detector<Default, void, Template, Args...>::type;
}
#endif

View File

@@ -1,391 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_HL_HPP
#define BOOST_PARSER_DETAIL_HL_HPP
#include <boost/parser/config.hpp>
#include <boost/parser/tuple.hpp>
#include <boost/parser/detail/detection.hpp>
#include <type_traits>
#include <utility>
namespace boost { namespace parser { namespace detail::hl {
// Boost.Hana lite. These functions work with boost::hana::tuple and
// std::tuple.
struct forward
{
template<typename T>
decltype(auto) operator()(T && t)
{
return (T &&) t;
}
};
template<typename... Args>
constexpr auto make_tuple(Args &&... args)
{
#if BOOST_PARSER_USE_STD_TUPLE
return std::make_tuple((Args &&) args...);
#else
return hana::make_tuple((Args &&) args...);
#endif
}
template<typename T, typename U>
constexpr auto make_pair(T && t, U && u)
{
return hl::make_tuple((T &&) t, (U &&) u);
}
template<typename Tuple1, typename Tuple2>
constexpr auto concat(Tuple1 const & t1, Tuple2 const & t2)
{
#if BOOST_PARSER_USE_STD_TUPLE
return std::tuple_cat(t1, t2);
#else
// Hana's concat does not seem to do what it says on the tin.
// Concatenating (int, string) with (double, int) yields (int, string,
// double). I maybe don't understand it well enough.
return hana::insert_range(t1, hana::size(t1), t2);
#endif
}
// for_each
template<typename F, typename Tuple, std::size_t... I>
constexpr void for_each_impl(
Tuple const & t, F && f, std::integer_sequence<std::size_t, I...>)
{
int _[] = {0, (f(parser::get(t, llong<I>{})), 0)...};
(void)_;
}
template<
typename F,
typename Tuple,
std::size_t... I,
typename Enable = std::enable_if_t<!std::is_reference_v<Tuple>>>
constexpr void
for_each_impl(Tuple && t, F && f, std::integer_sequence<std::size_t, I...>)
{
int _[] = {0, (f(std::move(parser::get(t, llong<I>{}))), 0)...};
(void)_;
}
template<typename F, typename... Args>
constexpr void for_each(tuple<Args...> && t, F && f)
{
hl::for_each_impl(
std::move(t),
(F &&) f,
std::make_integer_sequence<std::size_t, sizeof...(Args)>());
}
template<typename F, typename... Args>
constexpr void for_each(tuple<Args...> const & t, F && f)
{
hl::for_each_impl(
t,
(F &&) f,
std::make_integer_sequence<std::size_t, sizeof...(Args)>());
}
// transform
template<int offset, typename F, typename Tuple, std::size_t... I>
constexpr auto transform_impl(
Tuple const & t, F && f, std::integer_sequence<std::size_t, I...>)
{
return tuple<
std::decay_t<decltype(f(parser::get(t, llong<I + offset>{})))>...>{
f(parser::get(t, llong<I + offset>{}))...};
}
template<
int offset,
typename F,
typename Tuple,
std::size_t... I,
typename Enable = std::enable_if_t<!std::is_reference_v<Tuple>>>
auto constexpr transform_impl(
Tuple && t, F && f, std::integer_sequence<std::size_t, I...>)
{
return tuple<std::decay_t<decltype(
f(std::move(parser::get(t, llong<I + offset>{}))))>...>{
f(std::move(parser::get(t, llong<I + offset>{})))...};
}
template<typename F, typename... Args>
constexpr auto transform(tuple<Args...> && t, F && f)
{
return hl::transform_impl<0>(
std::move(t),
(F &&) f,
std::make_integer_sequence<std::size_t, sizeof...(Args)>());
}
template<typename F, typename... Args>
constexpr auto transform(tuple<Args...> const & t, F && f)
{
return hl::transform_impl<0>(
t,
(F &&) f,
std::make_integer_sequence<std::size_t, sizeof...(Args)>());
}
// fold_left
template<std::size_t I, std::size_t N>
struct fold_left_dispatch
{
template<typename F, typename State, typename... Args>
constexpr static auto
call(tuple<Args...> const & t, State && s, F const & f)
{
return fold_left_dispatch<I + 1, N>::call(
t, f((State &&) s, parser::get(t, llong<I>{})), f);
}
};
template<std::size_t I>
struct fold_left_dispatch<I, I>
{
template<typename F, typename State, typename... Args>
constexpr static auto
call(tuple<Args...> const & t, State && s, F const & f)
{
return (State &&) s;
}
};
template<typename F, typename State, typename... Args>
constexpr auto fold_left(tuple<Args...> const & t, State && s, F const & f)
{
return hl::fold_left_dispatch<0, sizeof...(Args)>::call(
t, (State &&) s, (F &&) f);
}
// size
template<typename... Args>
constexpr auto size(tuple<Args...> const & t)
{
return llong<sizeof...(Args)>{};
}
template<typename... Args>
constexpr auto size_minus_one(tuple<Args...> const & t)
{
return llong<sizeof...(Args) - 1>{};
}
// contains
template<typename T, typename U>
using comparable = decltype(std::declval<T>() == std::declval<U>());
struct typesafe_equals
{
template<typename T, typename U>
constexpr bool operator()(T const & t, U const & u)
{
if constexpr (detail::is_detected_v<comparable, T, U>) {
return t == u;
} else {
return false;
}
}
};
template<typename T, typename Tuple, std::size_t... I>
constexpr bool contains_impl(
Tuple const & t, T const & x, std::integer_sequence<std::size_t, I...>)
{
typesafe_equals eq;
(void)eq;
return (eq(parser::get(t, llong<I>{}), x) || ...);
}
template<typename T, typename... Args>
constexpr bool contains(tuple<Args...> & t, T const & x)
{
return contains_impl(
t, x, std::make_integer_sequence<std::size_t, sizeof...(Args)>());
}
// front, back
template<typename Arg, typename... Args>
constexpr decltype(auto) front(tuple<Arg, Args...> & t)
{
return parser::get(t, llong<0>{});
}
template<typename Arg, typename... Args>
constexpr decltype(auto) front(tuple<Arg, Args...> const & t)
{
return parser::get(t, llong<0>{});
}
template<typename Arg, typename... Args>
constexpr decltype(auto) back(tuple<Arg, Args...> & t)
{
return parser::get(t, llong<sizeof...(Args)>{});
}
template<typename Arg, typename... Args>
constexpr decltype(auto) back(tuple<Arg, Args...> const & t)
{
return parser::get(t, llong<sizeof...(Args)>{});
}
// drop_front
template<typename Arg, typename... Args>
constexpr auto drop_front(tuple<Arg, Args...> && t)
{
return hl::transform_impl<1>(
std::move(t),
forward{},
std::make_integer_sequence<std::size_t, sizeof...(Args)>());
}
template<typename Arg, typename... Args>
constexpr auto drop_front(tuple<Arg, Args...> const & t)
{
return hl::transform_impl<1>(
t,
forward{},
std::make_integer_sequence<std::size_t, sizeof...(Args)>());
}
// drop_back
template<typename Arg, typename... Args>
constexpr auto drop_back(tuple<Arg, Args...> && t)
{
return hl::transform_impl<0>(
std::move(t),
forward{},
std::make_integer_sequence<std::size_t, sizeof...(Args)>());
}
template<typename Arg, typename... Args>
constexpr auto drop_back(tuple<Arg, Args...> const & t)
{
return hl::transform_impl<0>(
t,
forward{},
std::make_integer_sequence<std::size_t, sizeof...(Args)>());
}
// first, second
template<typename T, typename U>
constexpr decltype(auto) first(tuple<T, U> & t)
{
return parser::get(t, llong<0>{});
}
template<typename T, typename U>
constexpr decltype(auto) first(tuple<T, U> const & t)
{
return parser::get(t, llong<0>{});
}
template<typename T, typename U>
constexpr decltype(auto) second(tuple<T, U> & t)
{
return parser::get(t, llong<1>{});
}
template<typename T, typename U>
constexpr decltype(auto) second(tuple<T, U> const & t)
{
return parser::get(t, llong<1>{});
}
// zip
template<std::size_t I, typename... Tuples>
constexpr decltype(auto) make_zip_elem(Tuples const &... ts)
{
return hl::make_tuple(parser::get(ts, llong<I>{})...);
}
template<std::size_t... I, typename... Tuples>
constexpr auto zip_impl(std::index_sequence<I...>, Tuples const &... ts)
{
return hl::make_tuple(hl::make_zip_elem<I>(ts...)...);
}
template<typename T>
struct tuplesize;
template<typename... Args>
struct tuplesize<tuple<Args...>>
{
constexpr static std::size_t value = sizeof...(Args);
};
template<typename Tuple, typename... Tuples>
constexpr auto zip(Tuple const & t, Tuples const &... ts)
{
return hl::zip_impl(
std::make_integer_sequence<
std::size_t,
tuplesize<std::remove_reference_t<Tuple>>::value>(),
t,
ts...);
}
// append
template<typename... Args, typename T>
constexpr auto append(tuple<Args...> && t, T && x)
{
#if BOOST_PARSER_USE_STD_TUPLE
return std::tuple_cat(std::move(t), std::make_tuple((T &&) x));
#else
return hana::append(std::move(t), (T &&) x);
#endif
}
template<typename... Args, typename T>
constexpr auto append(tuple<Args...> const & t, T && x)
{
#if BOOST_PARSER_USE_STD_TUPLE
return std::tuple_cat(t, std::make_tuple((T &&) x));
#else
return hana::append(t, (T &&) x);
#endif
}
// prepend
template<typename... Args, typename T>
constexpr auto prepend(tuple<Args...> && t, T && x)
{
#if BOOST_PARSER_USE_STD_TUPLE
return std::tuple_cat(std::make_tuple((T &&) x), std::move(t));
#else
return hana::prepend(std::move(t), (T &&) x);
#endif
}
template<typename... Args, typename T>
constexpr auto prepend(tuple<Args...> const & t, T && x)
{
#if BOOST_PARSER_USE_STD_TUPLE
return std::tuple_cat(std::make_tuple((T &&) x), t);
#else
return hana::prepend(t, (T &&) x);
#endif
}
}}}
#endif

View File

@@ -1,969 +0,0 @@
/*=============================================================================
Copyright (c) 2001-2014 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
Copyright (c) 2011 Jan Frederick Eick
Copyright (c) 2011 Christopher Jefferson
Copyright (c) 2006 Stephen Nutt
Copyright (c) 2019 T. Zachary Laine
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#ifndef BOOST_PARSER_DETAIL_NUMERIC_HPP
#define BOOST_PARSER_DETAIL_NUMERIC_HPP
#include <cmath>
namespace boost { namespace parser { namespace detail_spirit_x3 {
struct unused_type{};
// Copied from boost/spirit/home/support/char_class.hpp (Boost 1.71), and
// modified not to use Boost.TypeTraits.
template <typename TargetChar, typename SourceChar>
TargetChar cast_char(SourceChar ch)
{
if (std::is_signed_v<TargetChar> != std::is_signed_v<SourceChar>)
{
if (std::is_signed<SourceChar>::value)
{
// source is signed, target is unsigned
typedef std::make_unsigned_t<SourceChar> USourceChar;
return TargetChar(USourceChar(ch));
}
else
{
// source is unsigned, target is signed
typedef std::make_signed_t<SourceChar> SSourceChar;
return TargetChar(SSourceChar(ch));
}
}
else
{
// source and target has same signedness
return TargetChar(ch); // just cast
}
}
// Copied from
// boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp
// (Boost 1.67), and modified not to use Boost.MPL or Boost.PP.
inline constexpr int log2_table[] = {
0, 0, 1000000, 1584960, 2000000, 2321920, 2584960, 2807350,
3000000, 3169920, 3321920, 3459430, 3584960, 3700430, 3807350, 3906890,
4000000, 4087460, 4169920, 4247920, 4321920, 4392310, 4459430, 4523560,
4584960, 4643850, 4700430, 4754880, 4807350, 4857980, 4906890, 4954190,
5000000, 5044390, 5087460, 5129280, 5169925};
template<typename T, unsigned Radix>
struct digits_traits
{
static_assert(std::numeric_limits<T>::radix == 2, "");
constexpr static int value =
int((std::numeric_limits<T>::digits * 1000000) / log2_table[Radix]);
};
template <typename T>
struct digits_traits<T, 10>
{
static int constexpr value = std::numeric_limits<T>::digits10;
};
template<unsigned Radix>
struct radix_traits
{
template <typename Char>
inline static bool is_valid(Char ch)
{
if (Radix <= 10)
return (ch >= '0' && ch <= static_cast<Char>('0' + Radix -1));
return (ch >= '0' && ch <= '9')
|| (ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1))
|| (ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1));
}
template <typename Char>
inline static unsigned digit(Char ch)
{
if (Radix <= 10 || (ch >= '0' && ch <= '9'))
return ch - '0';
return std::tolower(detail_spirit_x3::cast_char<char>(ch)) - 'a' + 10;
}
};
template <unsigned Radix>
struct positive_accumulator
{
template <typename T, typename Char>
inline static void add(T& n, Char ch, std::false_type) // unchecked add
{
const int digit = radix_traits<Radix>::digit(ch);
n = n * T(Radix) + T(digit);
}
template <typename T, typename Char>
inline static bool add(T& n, Char ch, std::true_type) // checked add
{
// Ensure n *= Radix will not overflow
T const max = (std::numeric_limits<T>::max)();
T const val = max / Radix;
if (n > val)
return false;
T tmp = n * Radix;
// Ensure n += digit will not overflow
const int digit = radix_traits<Radix>::digit(ch);
if (tmp > max - digit)
return false;
n = tmp + static_cast<T>(digit);
return true;
}
};
template <unsigned Radix>
struct negative_accumulator
{
template <typename T, typename Char>
inline static void add(T& n, Char ch, std::false_type) // unchecked subtract
{
const int digit = radix_traits<Radix>::digit(ch);
n = n * T(Radix) - T(digit);
}
template <typename T, typename Char>
inline static bool add(T& n, Char ch, std::true_type) // checked subtract
{
// Ensure n *= Radix will not underflow
T const min = (std::numeric_limits<T>::min)();
T const val = min / T(Radix);
if (n < val)
return false;
T tmp = n * Radix;
// Ensure n -= digit will not underflow
int const digit = radix_traits<Radix>::digit(ch);
if (tmp < min + digit)
return false;
n = tmp - static_cast<T>(digit);
return true;
}
};
template <unsigned Radix, typename Accumulator, int MaxDigits>
struct int_extractor
{
template <typename Char, typename T>
inline static bool
call(Char ch, std::size_t count, T& n, std::true_type)
{
std::size_t constexpr
overflow_free = digits_traits<T, Radix>::value - 1;
if (count < overflow_free)
{
Accumulator::add(n, ch, std::false_type{});
}
else
{
if (!Accumulator::add(n, ch, std::true_type{}))
return false; // over/underflow!
}
return true;
}
template <typename Char, typename T>
inline static bool
call(Char ch, std::size_t /*count*/, T& n, std::false_type)
{
// no need to check for overflow
Accumulator::add(n, ch, std::false_type{});
return true;
}
template <typename Char>
inline static bool
call(Char /*ch*/, std::size_t /*count*/, unused_type, std::false_type)
{
return true;
}
template <typename Char, typename T>
inline static bool
call(Char ch, std::size_t count, T& n)
{
return call(ch, count, n
, std::integral_constant<bool,
( (MaxDigits < 0)
|| (MaxDigits > digits_traits<T, Radix>::value)
)
&& std::numeric_limits<T>::is_bounded
>()
);
}
};
template <int MaxDigits>
struct check_max_digits
{
inline static bool
call(std::size_t count)
{
return count < MaxDigits; // bounded
}
};
template <>
struct check_max_digits<-1>
{
inline static bool
call(std::size_t /*count*/)
{
return true; // unbounded
}
};
template <
typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
, typename Accumulator = positive_accumulator<Radix>
, bool Accumulate = false
>
struct extract_int_impl
{
template <typename Iterator, typename Sentinel, typename Attribute>
inline static bool
parse_main(
Iterator& first
, Sentinel last
, Attribute& attr)
{
typedef radix_traits<Radix> radix_check;
typedef int_extractor<Radix, Accumulator, MaxDigits> extractor;
typedef
typename std::iterator_traits<Iterator>::value_type char_type;
Iterator it = first;
std::size_t leading_zeros = 0;
if (!Accumulate)
{
// skip leading zeros
while (it != last && *it == '0' && leading_zeros < MaxDigits)
{
++it;
++leading_zeros;
}
}
typedef Attribute attribute_type;
attribute_type val = Accumulate ? attr : attribute_type(0);
std::size_t count = 0;
char_type ch;
while (true)
{
if (!check_max_digits<MaxDigits>::call(count + leading_zeros) ||
it == last)
break;
ch = *it;
if (!radix_check::is_valid(ch) ||
!extractor::call(ch, count, val))
break;
++it;
++count;
if (!check_max_digits<MaxDigits>::call(count + leading_zeros) ||
it == last)
break;
ch = *it;
if (!radix_check::is_valid(ch) ||
!extractor::call(ch, count, val))
break;
++it;
++count;
if (!check_max_digits<MaxDigits>::call(count + leading_zeros) ||
it == last)
break;
ch = *it;
if (!radix_check::is_valid(ch) ||
!extractor::call(ch, count, val))
break;
++it;
++count;
}
if (count + leading_zeros >= MinDigits)
{
attr = val;
first = it;
return true;
}
return false;
}
template <typename Iterator, typename Sentinel>
inline static bool
parse(
Iterator& first
, Sentinel last
, unused_type)
{
T n = 0; // must calculate value to detect over/underflow
return parse_main(first, last, n);
}
template <typename Iterator, typename Sentinel, typename Attribute>
inline static bool
parse(
Iterator& first
, Sentinel last
, Attribute& attr)
{
return parse_main(first, last, attr);
}
};
template <typename T, unsigned Radix, typename Accumulator, bool Accumulate>
struct extract_int_impl<T, Radix, 1, -1, Accumulator, Accumulate>
{
template <typename Iterator, typename Sentinel, typename Attribute>
inline static bool
parse_main(
Iterator& first
, Sentinel last
, Attribute& attr)
{
typedef radix_traits<Radix> radix_check;
typedef int_extractor<Radix, Accumulator, -1> extractor;
typedef
typename std::iterator_traits<Iterator>::value_type char_type;
Iterator it = first;
std::size_t count = 0;
if (!Accumulate)
{
// skip leading zeros
while (it != last && *it == '0')
{
++it;
++count;
}
if (it == last)
{
if (count == 0) // must have at least one digit
return false;
attr = 0;
first = it;
return true;
}
}
typedef Attribute attribute_type;
attribute_type val = Accumulate ? attr : attribute_type(0);
char_type ch = *it;
if (!radix_check::is_valid(ch) || !extractor::call(ch, 0, val))
{
if (count == 0) // must have at least one digit
return false;
attr = val;
first = it;
return true;
}
count = 0;
++it;
while (true)
{
if (it == last)
break;
ch = *it;
if (!radix_check::is_valid(ch))
break;
if (!extractor::call(ch, count, val))
return false;
++it;
++count;
if (it == last)
break;
ch = *it;
if (!radix_check::is_valid(ch))
break;
if (!extractor::call(ch, count, val))
return false;
++it;
++count;
if (it == last)
break;
ch = *it;
if (!radix_check::is_valid(ch))
break;
if (!extractor::call(ch, count, val))
return false;
++it;
++count;
}
attr = val;
first = it;
return true;
}
template <typename Iterator, typename Sentinel>
inline static bool
parse(
Iterator& first
, Sentinel last
, unused_type)
{
T n = 0; // must calculate value to detect over/underflow
return parse_main(first, last, n);
}
template <typename Iterator, typename Sentinel, typename Attribute>
inline static bool
parse(
Iterator& first
, Sentinel last
, Attribute& attr)
{
return parse_main(first, last, attr);
}
};
// Copied from boost/spirit/home/x3/support/numeric_utils/extract_int.hpp
// (Boost 1.67), and modified for use with iterator, sentinel pairs:
///////////////////////////////////////////////////////////////////////////
// Extract the prefix sign (- or +), return true if a '-' was found
///////////////////////////////////////////////////////////////////////////
template<typename Iterator, typename Sentinel>
inline bool extract_sign(Iterator & first, Sentinel last)
{
(void)last; // silence unused warnings
BOOST_PARSER_DEBUG_ASSERT(first != last); // precondition
// Extract the sign
bool neg = *first == '-';
if (neg || (*first == '+'))
{
++first;
return neg;
}
return false;
}
///////////////////////////////////////////////////////////////////////////
// Low level unsigned integer parser
///////////////////////////////////////////////////////////////////////////
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
, bool Accumulate = false>
struct extract_uint
{
// check template parameter 'Radix' for validity
static_assert(
(Radix >= 2 && Radix <= 36),
"Error Unsupported Radix");
template <typename Iterator, typename Sentinel>
inline static bool call(Iterator& first, Sentinel last, T& attr)
{
if (first == last)
return false;
typedef extract_int_impl<
T
, Radix
, MinDigits
, MaxDigits
, positive_accumulator<Radix>
, Accumulate>
extract_type;
Iterator save = first;
if (!extract_type::parse(first, last, attr))
{
first = save;
return false;
}
return true;
}
};
///////////////////////////////////////////////////////////////////////////
// Low level signed integer parser
///////////////////////////////////////////////////////////////////////////
template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
struct extract_int
{
// check template parameter 'Radix' for validity
static_assert(
(Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16),
"Error Unsupported Radix");
template <typename Iterator, typename Sentinel>
inline static bool call(Iterator& first, Sentinel last, T& attr)
{
if (first == last)
return false;
typedef extract_int_impl<
T, Radix, MinDigits, MaxDigits>
extract_pos_type;
typedef extract_int_impl<
T, Radix, MinDigits, MaxDigits, negative_accumulator<Radix> >
extract_neg_type;
Iterator save = first;
bool hit = detail_spirit_x3::extract_sign(first, last);
if (hit)
hit = extract_neg_type::parse(first, last, attr);
else
hit = extract_pos_type::parse(first, last, attr);
if (!hit)
{
first = save;
return false;
}
return true;
}
};
// Copied from boost/spirit/home/x3/support/numeric_utils/extract_real.hpp
// (Boost 1.71), and modified for use with iterator, sentinel pairs:
template <typename T, typename Enable = void>
struct pow10_helper
{
static T call(unsigned dim)
{
return std::pow(T(10), T(dim));
}
};
template <typename T>
struct pow10_table
{
constexpr static std::size_t size =
std::numeric_limits<T>::max_exponent10;
constexpr pow10_table()
: exponents()
{
exponents[0] = T(1);
for (auto i = 1; i != size; ++i)
exponents[i] = exponents[i-1] * T(10);
}
T exponents[size];
};
template <typename T>
struct native_pow10_helper
{
constexpr static auto table = pow10_table<T>();
static T call(unsigned dim)
{
return table.exponents[dim];
}
};
template <>
struct pow10_helper<float>
: native_pow10_helper<float> {};
template <>
struct pow10_helper<double>
: native_pow10_helper<double> {};
template <>
struct pow10_helper<long double>
: native_pow10_helper<long double> {};
template <typename T>
inline T pow10(unsigned dim)
{
return detail_spirit_x3::pow10_helper<T>::call(dim);
}
template<typename T>
inline bool scale(int exp, T & n)
{
constexpr auto max_exp = std::numeric_limits<T>::max_exponent10;
constexpr auto min_exp = std::numeric_limits<T>::min_exponent10;
if (exp >= 0)
{
// return false if exp exceeds the max_exp
// do this check only for primitive types!
if (std::is_floating_point_v<T> && exp > max_exp)
return false;
n *= detail_spirit_x3::pow10<T>(exp);
}
else
{
if (exp < min_exp)
{
n /= detail_spirit_x3::pow10<T>(-min_exp);
// return false if exp still exceeds the min_exp
// do this check only for primitive types!
exp += -min_exp;
if (std::is_floating_point_v<T> && exp < min_exp)
return false;
n /= detail_spirit_x3::pow10<T>(-exp);
}
else
{
n /= detail_spirit_x3::pow10<T>(-exp);
}
}
return true;
}
template<typename T>
bool scale(int exp, int frac, T & n)
{
return detail_spirit_x3::scale(exp - frac, n);
}
template<typename T>
T negate(bool neg, T n)
{
return neg ? -n : n;
}
template <typename T, typename RealPolicies>
struct extract_real
{
template <typename Iterator, typename Sentinel, typename Attribute>
static bool
parse(Iterator& first, Sentinel last, Attribute& attr,
RealPolicies const& p)
{
if (first == last)
return false;
Iterator save = first;
// Start by parsing the sign. neg will be true if
// we got a "-" sign, false otherwise.
bool neg = p.parse_sign(first, last);
// Now attempt to parse an integer
T n = 0;
bool got_a_number = p.parse_n(first, last, n);
// If we did not get a number it might be a NaN, Inf or a leading
// dot.
if (!got_a_number)
{
// Check whether the number to parse is a NaN or Inf
if (p.parse_nan(first, last, n) ||
p.parse_inf(first, last, n))
{
// If we got a negative sign, negate the number
attr = detail_spirit_x3::negate(neg, n);
return true; // got a NaN or Inf, return early
}
// If we did not get a number and our policies do not
// allow a leading dot, fail and return early (no-match)
if (!p.allow_leading_dot)
{
first = save;
return false;
}
}
bool e_hit = false;
Iterator e_pos;
int frac_digits = 0;
// Try to parse the dot ('.' decimal point)
if (p.parse_dot(first, last))
{
// We got the decimal point. Now we will try to parse
// the fraction if it is there. If not, it defaults
// to zero (0) only if we already got a number.
Iterator savef = first;
if (p.parse_frac_n(first, last, n))
{
// Optimization note: don't compute frac_digits if T is
// an unused_type. This should be optimized away by the compiler.
if (!std::is_same_v<T, unused_type>)
frac_digits =
static_cast<int>(std::distance(savef, first));
BOOST_PARSER_DEBUG_ASSERT(frac_digits >= 0);
}
else if (!got_a_number || !p.allow_trailing_dot)
{
// We did not get a fraction. If we still haven't got a
// number and our policies do not allow a trailing dot,
// return no-match.
first = save;
return false;
}
// Now, let's see if we can parse the exponent prefix
e_pos = first;
e_hit = p.parse_exp(first, last);
}
else
{
// No dot and no number! Return no-match.
if (!got_a_number)
{
first = save;
return false;
}
// If we must expect a dot and we didn't see an exponent
// prefix, return no-match.
e_pos = first;
e_hit = p.parse_exp(first, last);
if (p.expect_dot && !e_hit)
{
first = save;
return false;
}
}
if (e_hit)
{
// We got the exponent prefix. Now we will try to parse the
// actual exponent. It is an error if it is not there.
int exp = 0;
if (p.parse_exp_n(first, last, exp))
{
// Got the exponent value. Scale the number by
// exp-frac_digits.
if (!detail_spirit_x3::scale(exp, frac_digits, n))
return false;
}
else
{
// If there is no number, disregard the exponent altogether.
// by resetting 'first' prior to the exponent prefix (e|E)
first = e_pos;
// Scale the number by -frac_digits.
if (!detail_spirit_x3::scale(-frac_digits, n))
return false;
}
}
else if (frac_digits)
{
// No exponent found. Scale the number by -frac_digits.
if (!detail_spirit_x3::scale(-frac_digits, n))
return false;
}
// If we got a negative sign, negate the number
attr = detail_spirit_x3::negate(neg, n);
// Success!!!
return true;
}
};
// Copied from
// boost/spirit/home/x3/string/detail/string_parse.hpp
// (Boost 1.47),and modified for use with iterator, sentinel pairs:
struct common_type_equal
{
template<typename T, typename U>
bool operator()(T x, U y)
{
using common_t = std::common_type_t<decltype(x), decltype(y)>;
return (common_t)x == (common_t)y;
}
};
template <typename Char, typename Iterator, typename Sentinel>
inline bool string_parse(
Char const* uc_i, Char const* lc_i
, Iterator& first, Sentinel const& last)
{
Iterator i = first;
common_type_equal eq;
for (; *uc_i && *lc_i; ++uc_i, ++lc_i, ++i)
if (i == last || (!eq(*uc_i, *i) && !eq(*lc_i, *i)))
return false;
first = i;
return true;
}
// Copied from
// boost/spirit/home/x3/numeric/real_policies.hpp
// (Boost 1.47),and modified for use with iterator, sentinel pairs:
///////////////////////////////////////////////////////////////////////////
// Default (unsigned) real number policies
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct ureal_policies
{
// trailing dot policy suggested by Gustavo Guerra
static bool const allow_leading_dot = true;
static bool const allow_trailing_dot = true;
static bool const expect_dot = false;
template <typename Iterator, typename Sentinel>
static bool
parse_sign(Iterator& /*first*/, Iterator const& /*last*/)
{
return false;
}
template <typename Iterator, typename Sentinel, typename Attribute>
static bool
parse_n(Iterator& first, Sentinel const& last, Attribute& attr_)
{
return extract_uint<T, 10, 1, -1>::call(first, last, attr_);
}
template <typename Iterator, typename Sentinel>
static bool
parse_dot(Iterator& first, Sentinel const& last)
{
if (first == last || *first != '.')
return false;
++first;
return true;
}
template <typename Iterator, typename Sentinel, typename Attribute>
static bool
parse_frac_n(Iterator& first, Sentinel const& last, Attribute& attr_)
{
return extract_uint<T, 10, 1, -1, true>::call(first, last, attr_);
}
template <typename Iterator, typename Sentinel>
static bool
parse_exp(Iterator& first, Sentinel const& last)
{
if (first == last || (*first != 'e' && *first != 'E'))
return false;
++first;
return true;
}
template <typename Iterator, typename Sentinel>
static bool
parse_exp_n(Iterator& first, Sentinel const& last, int& attr_)
{
return extract_int<int, 10, 1, -1>::call(first, last, attr_);
}
///////////////////////////////////////////////////////////////////////
// The parse_nan() and parse_inf() functions get called whenever
// a number to parse does not start with a digit (after having
// successfully parsed an optional sign).
//
// The functions should return true if a Nan or Inf has been found. In
// this case the attr should be set to the matched value (NaN or
// Inf). The optional sign will be automatically applied afterwards.
//
// The default implementation below recognizes representations of NaN
// and Inf as mandated by the C99 Standard and as proposed for
// inclusion into the C++0x Standard: nan, nan(...), inf and infinity
// (the matching is performed case-insensitively).
///////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Sentinel, typename Attribute>
static bool
parse_nan(Iterator& first, Sentinel const& last, Attribute& attr_)
{
if (first == last)
return false; // end of input reached
if (*first != 'n' && *first != 'N')
return false; // not "nan"
// nan[(...)] ?
if (detail_spirit_x3::string_parse("nan", "NAN", first, last))
{
if (first != last && *first == '(')
{
// skip trailing (...) part
Iterator i = first;
while (++i != last && *i != ')')
;
if (i == last)
return false; // no trailing ')' found, give up
first = ++i;
}
attr_ = std::numeric_limits<T>::quiet_NaN();
return true;
}
return false;
}
template <typename Iterator, typename Sentinel, typename Attribute>
static bool
parse_inf(Iterator& first, Sentinel const& last, Attribute& attr_)
{
if (first == last)
return false; // end of input reached
if (*first != 'i' && *first != 'I')
return false; // not "inf"
// inf or infinity ?
if (detail_spirit_x3::string_parse("inf", "INF", first, last))
{
// skip allowed 'inity' part of infinity
detail_spirit_x3::string_parse("inity", "INITY", first, last);
attr_ = std::numeric_limits<T>::infinity();
return true;
}
return false;
}
};
///////////////////////////////////////////////////////////////////////////
// Default (signed) real number policies
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct real_policies : ureal_policies<T>
{
template <typename Iterator, typename Sentinel>
static bool
parse_sign(Iterator& first, Sentinel const& last)
{
return detail_spirit_x3::extract_sign(first, last);
}
};
template <typename T>
struct strict_ureal_policies : ureal_policies<T>
{
static bool const expect_dot = true;
};
template <typename T>
struct strict_real_policies : real_policies<T>
{
static bool const expect_dot = true;
};
}}}
#endif

View File

@@ -1,123 +0,0 @@
#ifndef BOOST_PARSER_DETAIL_PP_FOR_EACH_HPP_INCLUDED
#define BOOST_PARSER_DETAIL_PP_FOR_EACH_HPP_INCLUDED
// Copyright 2020 Peter Dimov
// Copyright 2023 T. Zachary Laine
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/parser/detail/pp_utilities.hpp>
#define BOOST_PARSER_PP_FOR_EACH_0(F, a)
#define BOOST_PARSER_PP_FOR_EACH_1(F, a, x) BOOST_PARSER_PP_CALL(F, a, x)
#define BOOST_PARSER_PP_FOR_EACH_2(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_1(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_3(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_2(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_4(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_3(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_5(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_4(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_6(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_5(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_7(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_6(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_8(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_7(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_9(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_8(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_10(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_9(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_11(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_10(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_12(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_11(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_13(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_12(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_14(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_13(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_15(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_14(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_16(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_15(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_17(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_16(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_18(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_17(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_19(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_18(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_20(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_19(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_21(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_20(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_22(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_21(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_23(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_22(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_24(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_23(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_25(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_24(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_26(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_25(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_27(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_26(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_28(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_27(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_29(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_28(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_30(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_29(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_31(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_30(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_32(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_31(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_33(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_32(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_34(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_33(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_35(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_34(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_36(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_35(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_37(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_36(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_38(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_37(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_39(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_38(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_40(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_39(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_41(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_40(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_42(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_41(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_43(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_42(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_44(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_43(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_45(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_44(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_46(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_45(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_47(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_46(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_48(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_47(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_49(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_48(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_50(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_49(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_51(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_50(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FOR_EACH_52(F, a, x, ...) BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_FOR_EACH_51(F, a, __VA_ARGS__))
#define BOOST_PARSER_PP_FE_EXTRACT(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, V, ...) V
#define BOOST_PARSER_PP_FOR_EACH(F, ...) \
BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_EXPAND(BOOST_PARSER_PP_FE_EXTRACT(__VA_ARGS__, \
BOOST_PARSER_PP_FOR_EACH_52, \
BOOST_PARSER_PP_FOR_EACH_51, \
BOOST_PARSER_PP_FOR_EACH_50, \
BOOST_PARSER_PP_FOR_EACH_49, \
BOOST_PARSER_PP_FOR_EACH_48, \
BOOST_PARSER_PP_FOR_EACH_47, \
BOOST_PARSER_PP_FOR_EACH_46, \
BOOST_PARSER_PP_FOR_EACH_45, \
BOOST_PARSER_PP_FOR_EACH_44, \
BOOST_PARSER_PP_FOR_EACH_43, \
BOOST_PARSER_PP_FOR_EACH_42, \
BOOST_PARSER_PP_FOR_EACH_41, \
BOOST_PARSER_PP_FOR_EACH_40, \
BOOST_PARSER_PP_FOR_EACH_39, \
BOOST_PARSER_PP_FOR_EACH_38, \
BOOST_PARSER_PP_FOR_EACH_37, \
BOOST_PARSER_PP_FOR_EACH_36, \
BOOST_PARSER_PP_FOR_EACH_35, \
BOOST_PARSER_PP_FOR_EACH_34, \
BOOST_PARSER_PP_FOR_EACH_33, \
BOOST_PARSER_PP_FOR_EACH_32, \
BOOST_PARSER_PP_FOR_EACH_31, \
BOOST_PARSER_PP_FOR_EACH_30, \
BOOST_PARSER_PP_FOR_EACH_29, \
BOOST_PARSER_PP_FOR_EACH_28, \
BOOST_PARSER_PP_FOR_EACH_27, \
BOOST_PARSER_PP_FOR_EACH_26, \
BOOST_PARSER_PP_FOR_EACH_25, \
BOOST_PARSER_PP_FOR_EACH_24, \
BOOST_PARSER_PP_FOR_EACH_23, \
BOOST_PARSER_PP_FOR_EACH_22, \
BOOST_PARSER_PP_FOR_EACH_21, \
BOOST_PARSER_PP_FOR_EACH_20, \
BOOST_PARSER_PP_FOR_EACH_19, \
BOOST_PARSER_PP_FOR_EACH_18, \
BOOST_PARSER_PP_FOR_EACH_17, \
BOOST_PARSER_PP_FOR_EACH_16, \
BOOST_PARSER_PP_FOR_EACH_15, \
BOOST_PARSER_PP_FOR_EACH_14, \
BOOST_PARSER_PP_FOR_EACH_13, \
BOOST_PARSER_PP_FOR_EACH_12, \
BOOST_PARSER_PP_FOR_EACH_11, \
BOOST_PARSER_PP_FOR_EACH_10, \
BOOST_PARSER_PP_FOR_EACH_9, \
BOOST_PARSER_PP_FOR_EACH_8, \
BOOST_PARSER_PP_FOR_EACH_7, \
BOOST_PARSER_PP_FOR_EACH_6, \
BOOST_PARSER_PP_FOR_EACH_5, \
BOOST_PARSER_PP_FOR_EACH_4, \
BOOST_PARSER_PP_FOR_EACH_3, \
BOOST_PARSER_PP_FOR_EACH_2, \
BOOST_PARSER_PP_FOR_EACH_1, \
BOOST_PARSER_PP_FOR_EACH_0))(F, __VA_ARGS__))
#endif // #ifndef BOOST_PARSER_DETAIL_PP_FOR_EACH_HPP_INCLUDED

View File

@@ -1,93 +0,0 @@
#ifndef BOOST_PARSER_DETAIL_PP_UTILITIES_HPP_INCLUDED
#define BOOST_PARSER_DETAIL_PP_UTILITIES_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Copyright 2023 T. Zachary Laine
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define BOOST_PARSER_PP_EXPAND(x) x
#define BOOST_PARSER_PP_CAT(x, y) BOOST_PARSER_PP_CAT_I(x, y)
#define BOOST_PARSER_PP_CAT_I(x, ...) x ## __VA_ARGS__
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_PARSER_PP_FIRST(x) BOOST_PARSER_PP_FIRST_I((x))
#define BOOST_PARSER_PP_FIRST_I(x) BOOST_PARSER_PP_FIRST_II x
#define BOOST_PARSER_PP_FIRST_II(x, ...) x
#else
#define BOOST_PARSER_PP_FIRST(x) BOOST_PARSER_PP_FIRST_I(x)
#define BOOST_PARSER_PP_FIRST_I(x, ...) x
#endif
#define BOOST_PARSER_PP_IS_PAREN_I(x) BOOST_PARSER_PP_CAT(BOOST_PARSER_PP_IS_PAREN_I_, BOOST_PARSER_PP_IS_PAREN_II x)
#define BOOST_PARSER_PP_IS_PAREN_II(...) 0
#define BOOST_PARSER_PP_IS_PAREN_I_0 1,
#define BOOST_PARSER_PP_IS_PAREN_I_BOOST_PARSER_PP_IS_PAREN_II 0,
#define BOOST_PARSER_PP_IS_PAREN(x) BOOST_PARSER_PP_FIRST(BOOST_PARSER_PP_IS_PAREN_I(x))
#define BOOST_PARSER_PP_EMPTY
#define BOOST_PARSER_PP_IS_EMPTY(x) BOOST_PARSER_PP_IS_EMPTY_I(BOOST_PARSER_PP_IS_PAREN(x), BOOST_PARSER_PP_IS_PAREN(x BOOST_PARSER_PP_EMPTY ()))
#define BOOST_PARSER_PP_IS_EMPTY_I(x, y) BOOST_PARSER_PP_IS_EMPTY_II(x, y)
#define BOOST_PARSER_PP_IS_EMPTY_II(x, y) BOOST_PARSER_PP_IS_EMPTY_III(x, y)
#define BOOST_PARSER_PP_IS_EMPTY_III(x, y) BOOST_PARSER_PP_IS_EMPTY_III_ ## x ## y
#define BOOST_PARSER_PP_IS_EMPTY_III_00 0
#define BOOST_PARSER_PP_IS_EMPTY_III_01 1
#define BOOST_PARSER_PP_IS_EMPTY_III_10 0
#define BOOST_PARSER_PP_IS_EMPTY_III_11 0
#define BOOST_PARSER_PP_CALL(F, a, x) BOOST_PARSER_PP_CAT(BOOST_PARSER_PP_CALL_I_, BOOST_PARSER_PP_IS_EMPTY(x))(F, a, x)
#define BOOST_PARSER_PP_CALL_I_0(F, a, x) F(a, x)
#define BOOST_PARSER_PP_CALL_I_1(F, a, x)
#define BOOST_PARSER_PP_PARSE(x) BOOST_PARSER_PP_CAT(BOOST_PARSER_PP_PARSE_I_, BOOST_PARSER_PP_PARSE_II x)
#define BOOST_PARSER_PP_PARSE_II(...) 0, (__VA_ARGS__),
#define BOOST_PARSER_PP_PARSE_I_BOOST_PARSER_PP_PARSE_II 0, ~,
#define BOOST_PARSER_PP_PARSE_I_0 1
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_PARSER_PP_NAME(x) BOOST_PARSER_PP_NAME_I(BOOST_PARSER_PP_PARSE(x))
#define BOOST_PARSER_PP_NAME_I(x) BOOST_PARSER_PP_NAME_II((x))
#define BOOST_PARSER_PP_NAME_II(x) BOOST_PARSER_PP_NAME_III x
#define BOOST_PARSER_PP_NAME_III(x, y, z) #z
#else
#define BOOST_PARSER_PP_NAME(x) BOOST_PARSER_PP_NAME_I(BOOST_PARSER_PP_PARSE(x))
#define BOOST_PARSER_PP_NAME_I(x) BOOST_PARSER_PP_NAME_II(x)
#define BOOST_PARSER_PP_NAME_II(x, y, z) #z
#endif
// template<class C, class F> constexpr auto mfn( F C::* p ) { return p; }
// template<class C, class F> constexpr auto mfn( F * p ) { return p; }
#define BOOST_PARSER_PP_POINTER(C, x) BOOST_PARSER_PP_POINTER_I(C, BOOST_PARSER_PP_PARSE(x))
#define BOOST_PARSER_PP_EXPAND_V(...) __VA_ARGS__
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_PARSER_PP_POINTER_I(C, x) BOOST_PARSER_PP_POINTER_II((C, x))
#define BOOST_PARSER_PP_POINTER_II(x) BOOST_PARSER_PP_POINTER_III x
#define BOOST_PARSER_PP_POINTER_III(C, x, y, z) BOOST_PARSER_PP_POINTER_III_##x(C, y, z)
#define BOOST_PARSER_PP_POINTER_III_0(C, y, z) &C::z
#define BOOST_PARSER_PP_POINTER_III_1(C, y, z) ::boost::describe::detail::mfn<C, BOOST_PARSER_PP_EXPAND_V y>(&C::z)
#else
#define BOOST_PARSER_PP_POINTER_I(C, x) BOOST_PARSER_PP_POINTER_II(C, x)
#define BOOST_PARSER_PP_POINTER_II(C, x, y, z) BOOST_PARSER_PP_POINTER_III_##x(C, y, z)
#define BOOST_PARSER_PP_POINTER_III_0(C, y, z) &C::z
#define BOOST_PARSER_PP_POINTER_III_1(C, y, z) ::boost::describe::detail::mfn<C, BOOST_PARSER_PP_EXPAND_V y>(&C::z)
#endif
#endif // #ifndef BOOST_PARSER_DETAIL_PP_UTILITIES_HPP_INCLUDED

View File

@@ -1,616 +0,0 @@
#ifndef BOOST_PARSER_DETAIL_PRINTING_HPP
#define BOOST_PARSER_DETAIL_PRINTING_HPP
#include <boost/parser/parser_fwd.hpp>
#include <boost/parser/tuple.hpp>
#include <boost/parser/detail/detection.hpp>
#include <boost/parser/detail/hl.hpp>
#include <boost/parser/detail/text/unpack.hpp>
#include <boost/parser/detail/text/transcode_view.hpp>
#include <iomanip>
#include <iostream>
#include <optional>
#include <sstream>
#include <string>
#include <variant>
#include <cctype>
namespace boost { namespace parser { namespace detail {
template<typename Context>
decltype(auto) _indent(Context const & context);
template<typename Char>
std::ostream & print_char(std::ostream & os, Char c)
{
if constexpr (
#if defined(__cpp_char8_t)
std::is_same_v<
char8_t,
std::remove_cv_t<std::remove_reference_t<Char>>>
#else
false
#endif
) {
os << char(c);
} else {
os << c;
}
return os;
}
enum { parser_component_limit = 4 };
template<
typename Context,
typename Parser,
typename DelimiterParser,
typename MinType,
typename MaxType>
void print_parser(
Context const & context,
repeat_parser<Parser, DelimiterParser, MinType, MaxType> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Parser>
void print_parser(
Context const & context,
opt_parser<Parser> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename ParserTuple>
void print_parser(
Context const & context,
or_parser<ParserTuple> const & parser,
std::ostream & os,
int components = 0);
template<
typename Context,
typename ParserTuple,
typename BacktrackingTuple,
typename CombiningGroups>
void print_parser(
Context const & context,
seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Parser, typename Action>
void print_parser(
Context const & context,
action_parser<Parser, Action> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Parser>
void print_parser(
Context const & context,
omit_parser<Parser> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Parser>
void print_parser(
Context const & context,
raw_parser<Parser> const & parser,
std::ostream & os,
int components = 0);
#if defined(BOOST_PARSER_DOXYGEN) || defined(__cpp_lib_concepts)
template<typename Context, typename Parser>
void print_parser(
Context const & context,
string_view_parser<Parser> const & parser,
std::ostream & os,
int components = 0);
#endif
template<typename Context, typename Parser>
void print_parser(
Context const & context,
lexeme_parser<Parser> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Parser>
void print_parser(
Context const & context,
no_case_parser<Parser> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Parser, typename SkipParser>
void print_parser(
Context const & context,
skip_parser<Parser, SkipParser> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Parser, bool FailOnMatch>
void print_parser(
Context const & context,
expect_parser<Parser, FailOnMatch> const & parser,
std::ostream & os,
int components = 0);
template<
typename Context,
bool UseCallbacks,
typename Parser,
typename Attribute,
typename LocalState,
typename ParamsTuple>
void print_parser(
Context const & context,
rule_parser<
UseCallbacks,
Parser,
Attribute,
LocalState,
ParamsTuple> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename T>
void print_parser(
Context const & context,
symbol_parser<T> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Predicate>
void print_parser(
Context const & context,
eps_parser<Predicate> const & parser,
std::ostream & os,
int components = 0);
template<typename Context>
void print_parser(
Context const & context,
eps_parser<nope> const & parser,
std::ostream & os,
int components = 0);
template<typename Context>
void print_parser(
Context const & context,
eoi_parser const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Atribute>
void print_parser(
Context const & context,
attr_parser<Atribute> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Expected, typename AttributeType>
void print_parser(
Context const & context,
char_parser<Expected, AttributeType> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename Expected, typename AttributeType>
void print_parser(
Context const & context,
omit_parser<char_parser<Expected, AttributeType>> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename StrIter, typename StrSentinel>
void print_parser(
Context const & context,
string_parser<StrIter, StrSentinel> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename StrIter, typename StrSentinel>
void print_parser(
Context const & context,
omit_parser<string_parser<StrIter, StrSentinel>> const & parser,
std::ostream & os,
int components = 0);
template<typename Context>
void print_parser(
Context const & context,
ws_parser<true> const & parser,
std::ostream & os,
int components = 0);
template<typename Context>
void print_parser(
Context const & context,
ws_parser<false> const & parser,
std::ostream & os,
int components = 0);
template<typename Context>
void print_parser(
Context const & context,
bool_parser const & parser,
std::ostream & os,
int components = 0);
template<
typename Context,
typename T,
int Radix,
int MinDigits,
int MaxDigits,
typename Expected>
void print_parser(
Context const & context,
uint_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
std::ostream & os,
int components = 0);
template<
typename Context,
typename T,
int Radix,
int MinDigits,
int MaxDigits,
typename Expected>
void print_parser(
Context const & context,
int_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename T>
void print_parser(
Context const & context,
float_parser<T> const & parser,
std::ostream & os,
int components = 0);
template<typename Context>
void print_parser(
Context const & context,
float_parser<float> const & parser,
std::ostream & os,
int components = 0);
template<typename Context>
void print_parser(
Context const & context,
float_parser<double> const & parser,
std::ostream & os,
int components = 0);
template<typename Context, typename SwitchValue, typename OrParser>
void print_parser(
Context const & context,
switch_parser<SwitchValue, OrParser> const & parser,
std::ostream & os,
int components = 0);
enum { trace_indent_factor = 2 };
inline void trace_indent(int indent)
{
for (int i = 0, end = trace_indent_factor * indent; i != end; ++i) {
std::cout << ' ';
}
}
template<typename Iter, typename Sentinel, int SizeofValueType>
struct trace_input_impl
{
static void call(
std::ostream & os,
Iter first_,
Sentinel last_,
bool quote,
int64_t trace_input_cps)
{
auto utf8 = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_) | text::as_utf8;
auto first = utf8.begin();
auto last = utf8.end();
if (quote)
os << '"';
for (int64_t i = 0; i < trace_input_cps && first != last;
++i, ++first) {
detail::print_char(os, *first);
}
if (quote)
os << '"';
}
};
template<typename Iter, typename Sentinel>
struct trace_input_impl<Iter, Sentinel, 1>
{
static void call(
std::ostream & os,
Iter first_,
Sentinel last_,
bool quote,
int64_t trace_input_cps)
{
auto r = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_);
auto r_unpacked =
detail::text::unpack_iterator_and_sentinel(first_, last_);
auto utf32 = r | text::as_utf32;
auto first = utf32.begin();
auto const last = utf32.end();
for (int64_t i = 0; i < trace_input_cps && first != last; ++i) {
++first;
}
if (quote)
os << '"';
auto first_repacked = r_unpacked.repack(first.base());
for (Iter it = first_, end = first_repacked; it != end; ++it) {
detail::print_char(os, *it);
}
if (quote)
os << '"';
}
};
template<typename Iter, typename Sentinel>
inline void trace_input(
std::ostream & os,
Iter first,
Sentinel last,
bool quote = true,
int64_t trace_input_cps = 8)
{
trace_input_impl<Iter, Sentinel, sizeof(*first)>::call(
os, first, last, quote, trace_input_cps);
}
template<typename Iter, typename Sentinel>
inline void trace_begin_match(
Iter first, Sentinel last, int indent, std::string_view name)
{
detail::trace_indent(indent);
std::cout << "[begin " << name << "; input=";
detail::trace_input(std::cout, first, last);
std::cout << "]" << std::endl;
}
template<typename Iter, typename Sentinel>
inline void trace_end_match(
Iter first, Sentinel last, int indent, std::string_view name)
{
detail::trace_indent(indent);
std::cout << "[end " << name << "; input=";
detail::trace_input(std::cout, first, last);
std::cout << "]" << std::endl;
}
template<typename Iter, typename Sentinel, typename Context>
void trace_prefix(
Iter first,
Sentinel last,
Context const & context,
std::string_view name)
{
int & indent = detail::_indent(context);
detail::trace_begin_match(first, last, indent, name);
++indent;
}
template<typename Iter, typename Sentinel, typename Context>
void trace_suffix(
Iter first,
Sentinel last,
Context const & context,
std::string_view name)
{
int & indent = detail::_indent(context);
--indent;
detail::trace_end_match(first, last, indent, name);
}
template<typename T>
using streamable =
decltype(std::declval<std::ostream &>() << std::declval<T const &>());
template<typename T, bool Streamable = is_detected_v<streamable, T>>
struct printer
{
std::ostream & operator()(std::ostream & os, T const &)
{
return os << "<<unprintable-value>>";
}
};
template<typename T>
void print_printable(std::ostream & os, T const & x)
{
os << x;
}
inline void print_printable(std::ostream & os, char c)
{
if (std::isprint(c)) {
os << "'" << c << "'";
} else {
os << "'\\x" << std::hex << std::setw(2) << std::setfill('0')
<< (uint32_t)c << "'";
}
}
inline void print_printable(std::ostream & os, char32_t c)
{
if (c < 256) {
os << "U";
detail::print_printable(os, (char)c);
} else {
os << "U'\\U" << std::hex << std::setw(8) << std::setfill('0')
<< (uint32_t)c << "'";
}
}
template<typename T>
struct printer<T, true>
{
std::ostream & operator()(std::ostream & os, T const & x)
{
detail::print_printable(os, x);
return os;
}
};
template<typename T>
constexpr bool is_variant_v = false;
template<typename... Ts>
constexpr bool is_variant_v<std::variant<Ts...>> = true;
template<typename Attribute>
inline void print(std::ostream & os, Attribute const & attr)
{
using just_attribute =
std::remove_cv_t<std::remove_reference_t<Attribute>>;
if constexpr (is_tuple<just_attribute>{}) {
os << "(";
bool first = false;
hl::for_each(attr, [&](auto const & a) {
if (first)
os << ", ";
detail::print(os, a);
first = false;
});
os << ")\n";
} else if constexpr (is_optional_v<just_attribute>) {
if (!attr)
os << "<<empty>>";
else
detail::print(os, *attr);
} else if constexpr (is_variant_v<just_attribute>) {
os << "<<variant>>";
} else {
printer<just_attribute>{}(os, attr);
}
}
template<typename Attribute>
inline void print_attribute(Attribute const & attr, int indent)
{
detail::trace_indent(indent);
std::cout << "attribute: ";
detail::print(std::cout, attr);
std::cout << "\n";
}
inline void print_attribute(nope const &, int) {}
constexpr inline bool do_trace(flags f)
{
return (uint32_t(f) & uint32_t(flags::trace)) == uint32_t(flags::trace);
}
template<typename Context, typename T>
auto resolve(Context const & context, T const & x);
template<typename Context>
auto resolve(Context const &, nope n);
template<
typename Iter,
typename Sentinel,
typename Context,
typename Attribute>
struct scoped_trace_t
{
scoped_trace_t(
Iter & first,
Sentinel last,
Context const & context,
flags f,
Attribute const & attr,
std::string name) :
initial_first_(first),
first_(first),
last_(last),
context_(context),
flags_(f),
attr_(attr),
name_(std::move(name))
{
if (!detail::do_trace(flags_))
return;
detail::trace_prefix(first_, last_, context_, name_);
}
~scoped_trace_t()
{
if (!detail::do_trace(flags_))
return;
detail::trace_indent(detail::_indent(context_));
if (*context_.pass_) {
std::cout << "matched ";
detail::trace_input(std::cout, initial_first_, first_);
std::cout << "\n";
detail::print_attribute(
detail::resolve(context_, attr_),
detail::_indent(context_));
} else {
std::cout << "no match\n";
}
detail::trace_suffix(first_, last_, context_, name_);
}
Iter initial_first_;
Iter & first_;
Sentinel last_;
Context const & context_;
flags flags_;
Attribute const & attr_;
std::string name_;
};
template<
typename Parser,
typename Iter,
typename Sentinel,
typename Context,
typename Attribute>
auto scoped_trace(
Parser const & parser,
Iter & first,
Sentinel last,
Context const & context,
flags f,
Attribute const & attr)
{
std::stringstream oss;
if (detail::do_trace(f))
detail::print_parser(context, parser, oss);
return scoped_trace_t<Iter, Sentinel, Context, Attribute>(
first, last, context, f, attr, oss.str());
}
template<typename Context, typename Attribute>
auto final_trace(Context const & context, flags f, Attribute const & attr)
{
if (!detail::do_trace(f))
return;
std::cout << "--------------------\n";
if (*context.pass_) {
std::cout << "parse succeeded\n";
detail::print_attribute(detail::resolve(context, attr), 0);
} else {
std::cout << "parse failed\n";
}
std::cout << "--------------------" << std::endl;
}
}}}
#endif

View File

@@ -1,871 +0,0 @@
#ifndef BOOST_PARSER_DETAIL_PRINTING_IMPL_HPP
#define BOOST_PARSER_DETAIL_PRINTING_IMPL_HPP
#include <boost/parser/detail/printing.hpp>
#if __has_include(<boost/type_index.hpp>)
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include <boost/type_index.hpp>
#define BOOST_PARSER_HAVE_BOOST_TYPEINDEX 1
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
#else
#include <typeinfo>
#define BOOST_PARSER_HAVE_BOOST_TYPEINDEX 0
#endif
namespace boost { namespace parser { namespace detail {
template<typename T>
auto type_name()
{
#if BOOST_PARSER_HAVE_BOOST_TYPEINDEX
return typeindex::type_id<T>().pretty_name();
#else
return typeid(T).name();
#endif
}
template<typename Parser>
struct n_aray_parser : std::false_type
{};
template<
typename Parser,
typename DelimiterParser,
typename MinType,
typename MaxType>
struct n_aray_parser<
repeat_parser<Parser, DelimiterParser, MinType, MaxType>>
: std::true_type
{};
template<typename Parser, typename MinType, typename MaxType>
struct n_aray_parser<repeat_parser<Parser, detail::nope, MinType, MaxType>>
: std::false_type
{};
template<typename Parser, typename DelimiterParser>
struct n_aray_parser<delimited_seq_parser<Parser, DelimiterParser>>
: std::true_type
{};
template<typename ParserTuple>
struct n_aray_parser<or_parser<ParserTuple>> : std::true_type
{};
template<
typename ParserTuple,
typename BacktrackingTuple,
typename CombiningGroups>
struct n_aray_parser<
seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups>>
: std::true_type
{};
// true iff Parser is an n-ary parser (contains N>2 subparsers).
template<typename Parser>
constexpr bool n_aray_parser_v = n_aray_parser<Parser>::value;
template<typename Context, typename Expected>
void print_expected(
Context const & context,
std::ostream & os,
Expected expected,
bool no_parens = false)
{
if (is_nope_v<Expected>)
return;
if (!no_parens)
os << "(";
detail::print(os, detail::resolve(context, expected));
if (!no_parens)
os << ")";
}
template<
typename Context,
typename Parser,
typename DelimiterParser,
typename MinType,
typename MaxType>
void print_parser(
Context const & context,
repeat_parser<Parser, DelimiterParser, MinType, MaxType> const & parser,
std::ostream & os,
int components)
{
if constexpr (is_nope_v<DelimiterParser>) {
auto const min_ = detail::resolve(context, parser.min_);
auto const max_ = detail::resolve(context, parser.max_);
constexpr bool n_ary_child = n_aray_parser_v<Parser>;
if (min_ == 0 && max_ == Inf) {
os << "*";
if (n_ary_child)
os << "(";
detail::print_parser(
context, parser.parser_, os, components + 1);
if (n_ary_child)
os << ")";
} else if (min_ == 1 && max_ == Inf) {
os << "+";
if (n_ary_child)
os << "(";
detail::print_parser(
context, parser.parser_, os, components + 1);
if (n_ary_child)
os << ")";
} else {
os << "repeat(";
detail::print(os, min_);
if (min_ == max_) {
os << ")[";
} else {
os << ", ";
if (max_ == unbounded)
os << "Inf";
else
detail::print(os, max_);
os << ")[";
}
detail::print_parser(
context, parser.parser_, os, components + 1);
os << "]";
}
} else {
detail::print_parser(context, parser.parser_, os, components + 1);
os << " % ";
detail::print_parser(
context, parser.delimiter_parser_, os, components + 2);
}
}
template<typename Context, typename Parser>
void print_parser(
Context const & context,
opt_parser<Parser> const & parser,
std::ostream & os,
int components)
{
os << "-";
constexpr bool n_ary_child = n_aray_parser_v<Parser>;
if (n_ary_child)
os << "(";
detail::print_parser(context, parser.parser_, os, components + 1);
if (n_ary_child)
os << ")";
}
template<typename Context, typename ParserTuple>
void print_parser(
Context const & context,
or_parser<ParserTuple> const & parser,
std::ostream & os,
int components)
{
int i = 0;
bool printed_ellipsis = false;
hl::for_each(parser.parsers_, [&](auto const & parser) {
if (components == parser_component_limit) {
if (!printed_ellipsis)
os << " | ...";
printed_ellipsis = true;
return;
}
if (i)
os << " | ";
detail::print_parser(context, parser, os, components);
++components;
++i;
});
}
template<
typename Context,
typename ParserTuple,
typename BacktrackingTuple,
typename CombiningGroups>
void print_parser(
Context const & context,
seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
parser,
std::ostream & os,
int components)
{
int prev_group = 0;
int i = 0;
bool printed_ellipsis = false;
using combining_groups =
detail::combining_t<ParserTuple, CombiningGroups>;
hl::for_each(
hl::zip(parser.parsers_, BacktrackingTuple{}, combining_groups{}),
[&](auto const & parser_and_backtrack) {
using namespace literals;
auto const & parser = parser::get(parser_and_backtrack, 0_c);
auto const backtrack = parser::get(parser_and_backtrack, 1_c);
auto const group = parser::get(parser_and_backtrack, 2_c);
if (components == parser_component_limit) {
if (!printed_ellipsis) {
os << (backtrack ? " >> ..." : " > ...");
}
printed_ellipsis = true;
return;
}
if (group != prev_group && prev_group)
os << ']';
if (i)
os << (backtrack ? " >> " : " > ");
if (group != prev_group && group)
os << (group == -1 ? "separate[" : "merge[");
detail::print_parser(context, parser, os, components);
++components;
++i;
prev_group = group;
});
if (prev_group && !printed_ellipsis)
os << ']';
}
template<typename Context, typename Parser, typename Action>
void print_parser(
Context const & context,
action_parser<Parser, Action> const & parser,
std::ostream & os,
int components)
{
detail::print_parser(context, parser.parser_, os, components);
os << "[<<action>>]";
}
template<typename Context, typename Parser>
void print_directive(
Context const & context,
std::string_view name,
Parser const & parser,
std::ostream & os,
int components)
{
os << name << "[";
if (++components == parser_component_limit)
os << "...";
else
detail::print_parser(context, parser, os, components + 1);
os << "]";
}
template<typename Context, typename Parser>
void print_parser(
Context const & context,
omit_parser<Parser> const & parser,
std::ostream & os,
int components)
{
detail::print_directive(
context, "omit", parser.parser_, os, components);
}
template<typename Context, typename Parser>
void print_parser(
Context const & context,
raw_parser<Parser> const & parser,
std::ostream & os,
int components)
{
detail::print_directive(context, "raw", parser.parser_, os, components);
}
#if defined(BOOST_PARSER_DOXYGEN) || defined(__cpp_lib_concepts)
template<typename Context, typename Parser>
void print_parser(
Context const & context,
string_view_parser<Parser> const & parser,
std::ostream & os,
int components)
{
detail::print_directive(
context, "string_view", parser.parser_, os, components);
}
#endif
template<typename Context, typename Parser>
void print_parser(
Context const & context,
lexeme_parser<Parser> const & parser,
std::ostream & os,
int components)
{
detail::print_directive(
context, "lexeme", parser.parser_, os, components);
}
template<typename Context, typename Parser>
void print_parser(
Context const & context,
no_case_parser<Parser> const & parser,
std::ostream & os,
int components)
{
detail::print_directive(
context, "no_case", parser.parser_, os, components);
}
template<typename Context, typename Parser, typename SkipParser>
void print_parser(
Context const & context,
skip_parser<Parser, SkipParser> const & parser,
std::ostream & os,
int components)
{
if constexpr (is_nope_v<SkipParser>) {
detail::print_directive(
context, "skip", parser.parser_, os, components);
} else {
os << "skip(";
detail::print_parser(
context, parser.skip_parser_.parser_, os, components);
os << ")";
detail::print_directive(
context, "", parser.parser_, os, components + 1);
}
}
template<typename Context, typename Parser, bool FailOnMatch>
void print_parser(
Context const & context,
expect_parser<Parser, FailOnMatch> const & parser,
std::ostream & os,
int components)
{
if (FailOnMatch)
os << "!";
else
os << "&";
constexpr bool n_ary_child = n_aray_parser_v<Parser>;
if (n_ary_child)
os << "(";
detail::print_parser(context, parser.parser_, os, components + 1);
if (n_ary_child)
os << ")";
}
template<
typename Context,
bool UseCallbacks,
typename Parser,
typename Attribute,
typename LocalState,
typename ParamsTuple>
void print_parser(
Context const & context,
rule_parser<
UseCallbacks,
Parser,
Attribute,
LocalState,
ParamsTuple> const & parser,
std::ostream & os,
int components)
{
os << parser.name_;
if constexpr (!is_nope_v<ParamsTuple>) {
os << ".with(";
int i = 0;
hl::for_each(parser.params_, [&](auto const & param) {
if (i++)
os << ", ";
detail::print_expected(context, os, param, true);
});
os << ")";
}
}
template<typename Context, typename T>
void print_parser(
Context const & context,
symbol_parser<T> const & parser,
std::ostream & os,
int components)
{
os << "symbols<" << detail::type_name<T>() << ">";
}
template<typename Context, typename Predicate>
void print_parser(
Context const & context,
eps_parser<Predicate> const & parser,
std::ostream & os,
int components)
{
os << "eps(<<pred>>)";
}
template<typename Context>
void print_parser(
Context const & context,
eps_parser<nope> const & parser,
std::ostream & os,
int components)
{
os << "eps";
}
template<typename Context>
void print_parser(
Context const & context,
eoi_parser const & parser,
std::ostream & os,
int components)
{
os << "eoi";
}
template<typename Context, typename Atribute>
void print_parser(
Context const & context,
attr_parser<Atribute> const & parser,
std::ostream & os,
int components)
{
os << "attr";
detail::print_expected(context, os, parser.attr_);
}
template<
typename Context,
typename ResolvedExpected,
bool Integral = std::is_integral<ResolvedExpected>{},
int SizeofExpected = sizeof(ResolvedExpected)>
struct print_expected_char_impl
{
static void call(
Context const & context,
std::ostream & os,
ResolvedExpected expected)
{
detail::print(os, expected);
}
};
template<typename Context, typename Expected>
struct print_expected_char_impl<Context, Expected, true, 4>
{
static void
call(Context const & context, std::ostream & os, Expected expected)
{
std::array<char32_t, 1> cps = {{(char32_t)expected}};
auto const r = cps | text::as_utf8;
os << "'";
for (auto c : r) {
detail::print_char(os, c);
}
os << "'";
}
};
template<typename Context, typename Expected>
void print_expected_char(
Context const & context, std::ostream & os, Expected expected)
{
auto resolved_expected = detail::resolve(context, expected);
detail::print_expected_char_impl<Context, decltype(resolved_expected)>::
call(context, os, resolved_expected);
}
template<typename Context, typename T>
struct char_print_parser_impl
{
static void call(Context const & context, std::ostream & os, T expected)
{
detail::print_expected_char(context, os, expected);
}
};
template<typename Context, typename T, typename U>
struct char_print_parser_impl<Context, char_pair<T, U>>
{
static void call(
Context const & context,
std::ostream & os,
char_pair<T, U> expected)
{
detail::print_expected_char(context, os, expected.lo_);
os << ", ";
detail::print_expected_char(context, os, expected.hi_);
}
};
template<typename Context, typename Iter, typename Sentinel>
struct char_print_parser_impl<Context, char_range<Iter, Sentinel>>
{
static void call(
Context const & context,
std::ostream & os,
char_range<Iter, Sentinel> expected)
{
os << "\"";
auto const r = expected.chars_ | text::as_utf8;
for (auto c : r) {
detail::print_char(os, c);
}
os << "\"";
}
};
template<typename Context, typename Expected, typename AttributeType>
void print_parser(
Context const & context,
char_parser<Expected, AttributeType> const & parser,
std::ostream & os,
int components)
{
if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::alnum>>) {
os << "ascii::alnum";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::alpha>>) {
os << "ascii::alpha";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::blank>>) {
os << "ascii::blank";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::cntrl>>) {
os << "ascii::cntrl";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::digit>>) {
os << "ascii::digit";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::graph>>) {
os << "ascii::graph";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::print>>) {
os << "ascii::print";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::punct>>) {
os << "ascii::punct";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::space>>) {
os << "ascii::space";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::xdigit>>) {
os << "ascii::xdigit";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::lower>>) {
os << "ascii::lower";
} else if (std::is_same_v<
Expected,
ascii_char_class<ascii_char_class_t::upper>>) {
os << "ascii::upper";
} else {
if (std::is_same_v<AttributeType, uint32_t>)
os << "cp";
else if (std::is_same_v<AttributeType, char>)
os << "cu";
else
os << "char_";
if constexpr (!is_nope_v<Expected>) {
os << "(";
char_print_parser_impl<Context, Expected>::call(
context, os, parser.expected_);
os << ")";
}
}
}
template<typename Context, typename Expected, typename AttributeType>
void print_parser(
Context const & context,
omit_parser<char_parser<Expected, AttributeType>> const & parser,
std::ostream & os,
int components)
{
if constexpr (is_nope_v<Expected>) {
os << "omit[char_]";
} else {
char_print_parser_impl<Context, Expected>::call(
context, os, parser.parser_.expected_);
}
}
template<typename Context, typename StrIter, typename StrSentinel>
void print_parser(
Context const & context,
string_parser<StrIter, StrSentinel> const & parser,
std::ostream & os,
int components)
{
os << "string(\"";
for (auto c : BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
parser.expected_first_, parser.expected_last_) |
text::as_utf8) {
detail::print_char(os, c);
}
os << "\")";
}
template<typename Context, typename StrIter, typename StrSentinel>
void print_parser(
Context const & context,
omit_parser<string_parser<StrIter, StrSentinel>> const & parser,
std::ostream & os,
int components)
{
os << "\"";
for (auto c : BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
parser.parser_.expected_first_,
parser.parser_.expected_last_) |
text::as_utf8) {
detail::print_char(os, c);
}
os << "\"";
}
template<typename Context>
void print_parser(
Context const & context,
ws_parser<true> const & parser,
std::ostream & os,
int components)
{
os << "eol";
}
template<typename Context>
void print_parser(
Context const & context,
ws_parser<false> const & parser,
std::ostream & os,
int components)
{
os << "ws";
}
template<typename Context>
void print_parser(
Context const & context,
bool_parser const & parser,
std::ostream & os,
int components)
{
os << "bool_";
}
template<
typename Context,
typename T,
int Radix,
int MinDigits,
int MaxDigits,
typename Expected>
void print_parser(
Context const & context,
uint_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
std::ostream & os,
int components)
{
if (MinDigits == 1 && MaxDigits == -1) {
if (std::is_same_v<T, unsigned short>) {
os << "ushort_";
detail::print_expected(context, os, parser.expected_);
return;
} else if (std::is_same_v<T, unsigned int>) {
if (Radix == 2)
os << "bin";
else if (Radix == 8)
os << "oct";
else if (Radix == 16)
os << "hex";
else if (Radix == 10)
os << "uint_";
detail::print_expected(context, os, parser.expected_);
return;
} else if (Radix == 10 && std::is_same_v<T, unsigned long>) {
os << "ulong_";
detail::print_expected(context, os, parser.expected_);
return;
} else if (Radix == 10 && std::is_same_v<T, unsigned long long>) {
os << "ulong_long";
detail::print_expected(context, os, parser.expected_);
return;
}
}
os << "uint<" << detail::type_name<T>() << ", " << Radix << ", "
<< MinDigits << ", " << MaxDigits << ">";
detail::print_expected(context, os, parser.expected_);
}
template<
typename Context,
typename T,
int Radix,
int MinDigits,
int MaxDigits,
typename Expected>
void print_parser(
Context const & context,
int_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
std::ostream & os,
int components)
{
if (Radix == 10 && MinDigits == 1 && MaxDigits == -1) {
if (std::is_same_v<T, short>) {
os << "short_";
detail::print_expected(context, os, parser.expected_);
return;
} else if (std::is_same_v<T, int>) {
os << "int_";
detail::print_expected(context, os, parser.expected_);
return;
} else if (std::is_same_v<T, long>) {
os << "long_";
detail::print_expected(context, os, parser.expected_);
return;
} else if (std::is_same_v<T, long long>) {
os << "long_long";
detail::print_expected(context, os, parser.expected_);
return;
}
}
os << "int<" << detail::type_name<T>() << ", " << Radix << ", "
<< MinDigits << ", " << MaxDigits << ">";
detail::print_expected(context, os, parser.expected_);
}
template<typename Context>
void print_parser(
Context const & context,
int_parser<short> const & parser,
std::ostream & os,
int components)
{
os << "short_";
}
template<typename Context>
void print_parser(
Context const & context,
int_parser<long> const & parser,
std::ostream & os,
int components)
{
os << "long_";
}
template<typename Context>
void print_parser(
Context const & context,
int_parser<long long> const & parser,
std::ostream & os,
int components)
{
os << "long_long";
}
template<typename Context, typename T>
void print_parser(
Context const & context,
float_parser<T> const & parser,
std::ostream & os,
int components)
{
os << "float<" << detail::type_name<T>() << ">";
}
template<typename Context>
void print_parser(
Context const & context,
float_parser<float> const & parser,
std::ostream & os,
int components)
{
os << "float_";
}
template<typename Context>
void print_parser(
Context const & context,
float_parser<double> const & parser,
std::ostream & os,
int components)
{
os << "double_";
}
template<
typename Context,
typename ParserTuple,
typename BacktrackingTuple,
typename CombiningGroups>
void print_switch_matchers(
Context const & context,
seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
parser,
std::ostream & os,
int components)
{
using namespace literals;
os << "("
<< detail::resolve(
context, parser::get(parser.parsers_, 0_c).pred_.value_)
<< ", ";
detail::print_parser(
context, parser::get(parser.parsers_, 1_c), os, components);
os << ")";
}
template<typename Context, typename ParserTuple>
void print_switch_matchers(
Context const & context,
or_parser<ParserTuple> const & parser,
std::ostream & os,
int components)
{
using namespace literals;
bool printed_ellipsis = false;
hl::for_each(parser.parsers_, [&](auto const & parser) {
if (components == parser_component_limit) {
if (!printed_ellipsis)
os << "...";
printed_ellipsis = true;
return;
}
detail::print_switch_matchers(context, parser, os, components);
++components;
});
}
template<typename Context, typename SwitchValue, typename OrParser>
void print_parser(
Context const & context,
switch_parser<SwitchValue, OrParser> const & parser,
std::ostream & os,
int components)
{
os << "switch_(";
detail::print(os, detail::resolve(context, parser.switch_value_));
os << ")";
detail::print_switch_matchers(
context, parser.or_parser_, os, components);
}
}}}
#endif

View File

@@ -1,48 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_STL_INTERFACES_CONFIG_HPP
#define BOOST_PARSER_DETAIL_STL_INTERFACES_CONFIG_HPP
#include <boost/parser/config.hpp>
#if !BOOST_PARSER_USE_CONCEPTS
# define BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS 0
#else
// This is now hard-coded to use the pre-C++20 code path. There are a bunch
// of really odd compile errorswith Clang+libstdc++ I can't be bothered to
// address right now. (The latest version of Boost.Text might fix these
// errors, but there's also no pre-C++20 code path in that version of Text.)
# define BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS 0
#endif
#if defined(__cpp_explicit_this_parameter) && BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
#define BOOST_PARSER_USE_DEDUCED_THIS 1
#else
#define BOOST_PARSER_USE_DEDUCED_THIS 0
#endif
// The inline namespaces v1, v2, and v3 represent C++14, C++20, and C++23 and
// later, respectively. v1 is inline for standards before C++20, and v2 is
// inline for C++20 and later. Note that this only applies to code for which
// multiple vI namespace alternatives exist. For example, some instances of
// the v1 namespace may still be inline, if there is no v2 version of its
// contents.
#if !BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS && !BOOST_PARSER_USE_DEDUCED_THIS
# define BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V1 inline namespace v1
# define BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V2 namespace v2
# define BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V3 namespace v3
#elif BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS && !BOOST_PARSER_USE_DEDUCED_THIS
# define BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V1 namespace v1
# define BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V2 inline namespace v2
# define BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V3 namespace v3
#else
# define BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V1 namespace v1
# define BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V2 namespace v2
# define BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V3 inline namespace v3
#endif
#endif

View File

@@ -1,152 +0,0 @@
// Copyright (C) 2022 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP
#define BOOST_PARSER_DETAIL_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP
#include <boost/parser/config.hpp>
#include <type_traits>
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
#include <ranges>
#endif
namespace boost::parser::detail { namespace stl_interfaces { namespace detail {
template<typename T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
struct pipeable_base;
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<typename T>
concept pipeable_ = std::derived_from<T, pipeable_base> &&
std::is_object_v<T> && std::copy_constructible<T>;
#else
template<typename T>
constexpr bool pipeable_ = std::is_base_of<pipeable_base, T>::value &&
std::is_object<T>::value && std::is_copy_constructible<T>::value;
#endif
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<pipeable_ T, pipeable_ U>
#else
template<
typename T,
typename U,
typename Enable = std::enable_if_t<pipeable_<T> && pipeable_<U>>>
#endif
struct view_pipeline;
struct pipeable_base
{
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<pipeable_ T, pipeable_ U>
requires std::constructible_from<std::remove_cvref_t<T>, T> &&
std::constructible_from<std::remove_cvref_t<U>, U>
#else
template<
typename T,
typename U,
typename Enable = std::enable_if_t<
pipeable_<T> && pipeable_<U> &&
std::is_constructible<remove_cvref_t<T>, T>::value &&
std::is_constructible<remove_cvref_t<U>, U>::value>>
#endif
friend constexpr auto operator|(T && t, U && u)
{
return view_pipeline<T, U>{(T &&) t, (U &&) u};
}
};
template<typename Derived>
struct pipeable : pipeable_base
{
template<typename R>
friend constexpr auto operator|(R && r, Derived & d)
-> decltype(((Derived &&) d)((R &&) r))
{
return ((Derived &&) d)((R &&) r);
}
template<typename R>
friend constexpr auto operator|(R && r, Derived const & d)
-> decltype(((Derived &&) d)((R &&) r))
{
return ((Derived &&) d)((R &&) r);
}
template<typename R>
friend constexpr auto operator|(R && r, Derived && d)
-> decltype(((Derived &&) d)((R &&) r))
{
return ((Derived &&) d)((R &&) r);
}
};
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<pipeable_ T, pipeable_ U>
#else
template<typename T, typename U, typename>
#endif
struct view_pipeline : pipeable<view_pipeline<T, U>>
{
view_pipeline() = default;
constexpr view_pipeline(T && t, U && u) :
left_(std::move(t)), right_(std::move(u))
{}
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::viewable_range R>
requires std::invocable<T &, R> &&
std::invocable<U &, std::invoke_result_t<T &, R>>
constexpr decltype(auto) operator()(R && r) &
#else
template<typename R>
constexpr auto
operator()(R && r) & -> decltype(this->right_(this->left_((R &&) r)))
#endif
{
return right_(left_((R &&) r));
}
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::viewable_range R>
requires std::invocable<T const &, R> &&
std::invocable<U const &, std::invoke_result_t<T const &, R>>
constexpr decltype(auto) operator()(R && r) const &
#else
template<typename R>
constexpr auto operator()(
R && r) const & -> decltype(this->right_(this->left_((R &&) r)))
#endif
{
return right_(left_((R &&) r));
}
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::viewable_range R>
requires std::invocable<T, R> &&
std::invocable<U, std::invoke_result_t<T, R>>
constexpr decltype(auto) operator()(R && r) &&
#else
template<typename R>
constexpr auto operator()(R && r) && -> decltype(std::move(
this->right_)(std::move(this->left_)((R &&) r)))
#endif
{
return std::move(right_)(std::move(left_)((R &&) r));
}
T left_;
U right_;
};
}}}
#endif

View File

@@ -1,107 +0,0 @@
// Copyright (C) 2022 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_STL_INTERFACES_DETAIL_VIEW_CLOSURE_HPP
#define BOOST_PARSER_DETAIL_STL_INTERFACES_DETAIL_VIEW_CLOSURE_HPP
#include <boost/parser/detail/stl_interfaces/detail/pipeable_view.hpp>
#include <utility>
namespace boost::parser::detail { namespace stl_interfaces { namespace detail {
template<std::size_t I, typename T>
struct box
{
T value_;
};
template<typename Indices, typename Func, typename... T>
struct view_closure_impl;
template<std::size_t... I, typename Func, typename... T>
struct view_closure_impl<std::index_sequence<I...>, Func, T...>
: box<I, T>...
{
view_closure_impl() = default;
constexpr explicit view_closure_impl(Func, T &&... x) :
box<I, T>{std::move(x)}...
{}
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::input_range R>
requires std::ranges::viewable_range<R> &&
std::invocable<Func, R, T &...> &&
std::ranges::view<std::invoke_result_t<Func, R, T &...>>
constexpr auto operator()(R && r) &
#else
template<typename R>
constexpr auto operator()(R && r) & -> decltype(
Func{}((R &&) r, std::declval<box<I, T> &>().value_...))
#endif
{
return Func{}((R &&) r, static_cast<box<I, T> &>(*this).value_...);
}
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::input_range R>
requires std::ranges::viewable_range<R> &&
std::invocable<Func, R, T const &...> &&
std::ranges::view<std::invoke_result_t<Func, R, T const &...>>
constexpr auto operator()(R && r) const &
#else
template<typename R>
constexpr auto operator()(R && r) const & -> decltype(
Func{}((R &&) r, std::declval<box<I, T> const &>().value_...))
#endif
{
return Func{}(
(R &&) r, static_cast<box<I, T> const &>(*this).value_...);
}
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::input_range R>
requires std::ranges::viewable_range<R> &&
std::invocable<Func, R, T...> &&
std::ranges::view<std::invoke_result_t<Func, R, T...>>
constexpr auto operator()(R && r) &&
#else
template<typename R>
constexpr auto operator()(R && r) && -> decltype(
Func{}((R &&) r, std::declval<box<I, T> &&>().value_...))
#endif
{
return Func{}((R &&) r, static_cast<box<I, T> &&>(*this).value_...);
}
};
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<std::semiregular Func, std::copy_constructible... T>
#else
template<typename Func, typename... T>
#endif
struct view_closure
: pipeable<view_closure<Func, T...>>,
view_closure_impl<std::index_sequence_for<T...>, Func, T...>
{
using base_type =
view_closure_impl<std::index_sequence_for<T...>, Func, T...>;
view_closure() = default;
constexpr explicit view_closure(Func func, T &&... x) :
base_type{func, std::move(x)...}
{}
};
#if defined(__cpp_deduction_guides)
template<typename Func, typename... T>
view_closure(Func, T...) -> view_closure<Func, T...>;
#endif
}}}
#endif

View File

@@ -1,86 +0,0 @@
// Copyright (C) 2019 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_STL_INTERFACES_FWD_HPP
#define BOOST_PARSER_DETAIL_STL_INTERFACES_FWD_HPP
#include <boost/parser/detail/stl_interfaces/config.hpp>
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
#include <ranges>
#endif
#if defined(__cpp_lib_three_way_comparison)
#include <compare>
#endif
namespace boost::parser::detail { namespace stl_interfaces {
/** An enumeration used to indicate whether the underlying data have a
contiguous or discontiguous layout when instantiating `view_interface`
and `sequence_container_interface`. */
enum class element_layout : bool {
discontiguous = false,
contiguous = true
};
BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V1 {
namespace v1_dtl {
template<typename... T>
using void_t = void;
template<typename Iter>
using iter_difference_t =
typename std::iterator_traits<Iter>::difference_type;
template<typename Range, typename = void>
struct iterator;
template<typename Range>
struct iterator<
Range,
void_t<decltype(std::declval<Range &>().begin())>>
{
using type = decltype(std::declval<Range &>().begin());
};
template<typename Range>
using iterator_t = typename iterator<Range>::type;
template<typename Range, typename = void>
struct sentinel;
template<typename Range>
struct sentinel<
Range,
void_t<decltype(std::declval<Range &>().end())>>
{
using type = decltype(std::declval<Range &>().end());
};
template<typename Range>
using sentinel_t = typename sentinel<Range>::type;
template<typename Range>
using range_difference_t = iter_difference_t<iterator_t<Range>>;
template<typename Range>
using common_range =
std::is_same<iterator_t<Range>, sentinel_t<Range>>;
template<typename Range, typename = void>
struct decrementable_sentinel : std::false_type
{
};
template<typename Range>
struct decrementable_sentinel<
Range,
void_t<decltype(--std::declval<sentinel_t<Range> &>())>>
: std::true_type
{
};
}
}
}}
#endif

View File

@@ -1,221 +0,0 @@
// Copyright (C) 2019 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_STL_INTERFACES_REVERSE_ITERATOR_HPP
#define BOOST_PARSER_DETAIL_STL_INTERFACES_REVERSE_ITERATOR_HPP
#include <boost/parser/detail/stl_interfaces/iterator_interface.hpp>
namespace boost::parser::detail { namespace stl_interfaces { BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V1 {
namespace v1_dtl {
template<typename Iter>
constexpr auto ce_dist(Iter f, Iter l, std::random_access_iterator_tag)
-> decltype(l - f)
{
return l - f;
}
template<typename Iter, typename Tag>
constexpr auto ce_dist(Iter f, Iter l, Tag)
-> decltype(std::distance(f, l))
{
decltype(std::distance(f, l)) retval = 0;
for (; f != l; ++f) {
++retval;
}
return retval;
}
template<typename Iter>
constexpr Iter ce_prev(Iter it)
{
return --it;
}
template<typename Iter, typename Offset>
constexpr void
ce_adv(Iter & f, Offset n, std::random_access_iterator_tag)
{
f += n;
}
template<typename Iter, typename Offset, typename Tag>
constexpr void ce_adv(Iter & f, Offset n, Tag)
{
if (0 < n) {
for (Offset i = 0; i < n; ++i) {
++f;
}
} else {
for (Offset i = 0; i < -n; ++i) {
--f;
}
}
}
}
/** This type is very similar to the C++20 version of
`std::reverse_iterator`; it is `constexpr`-, `noexcept`-, and
proxy-friendly. */
template<typename BidiIter>
struct reverse_iterator
: iterator_interface<
#if !BOOST_PARSER_USE_DEDUCED_THIS
reverse_iterator<BidiIter>,
#endif
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
typename boost::parser::detail::stl_interfaces::v2::v2_dtl::iter_concept_t<
BidiIter>,
#else
typename std::iterator_traits<BidiIter>::iterator_category,
#endif
typename std::iterator_traits<BidiIter>::value_type,
typename std::iterator_traits<BidiIter>::reference,
typename std::iterator_traits<BidiIter>::pointer,
typename std::iterator_traits<BidiIter>::difference_type>
{
constexpr reverse_iterator() noexcept(noexcept(BidiIter())) : it_() {}
constexpr reverse_iterator(BidiIter it) noexcept(
noexcept(BidiIter(it))) :
it_(it)
{}
template<
typename BidiIter2,
typename E = std::enable_if_t<
std::is_convertible<BidiIter2, BidiIter>::value>>
reverse_iterator(reverse_iterator<BidiIter2> const & it) : it_(it.it_)
{}
friend constexpr auto
operator-(reverse_iterator lhs, reverse_iterator rhs) noexcept(
noexcept(v1_dtl::ce_dist(
lhs.it_,
rhs.it_,
typename std::iterator_traits<BidiIter>::iterator_category{})))
{
return -v1_dtl::ce_dist(
rhs.it_,
lhs.it_,
typename std::iterator_traits<BidiIter>::iterator_category{});
}
constexpr typename std::iterator_traits<BidiIter>::reference
operator*() const noexcept(
noexcept(std::prev(v1_dtl::ce_prev(std::declval<BidiIter &>()))))
{
return *v1_dtl::ce_prev(it_);
}
constexpr reverse_iterator & operator+=(
typename std::iterator_traits<BidiIter>::difference_type
n) noexcept(noexcept(v1_dtl::
ce_adv(
std::declval<BidiIter &>(),
-n,
typename std::iterator_traits<
BidiIter>::
iterator_category{})))
{
v1_dtl::ce_adv(
it_,
-n,
typename std::iterator_traits<BidiIter>::iterator_category{});
return *this;
}
constexpr BidiIter base() const noexcept { return it_; }
private:
friend access;
constexpr BidiIter & base_reference() noexcept { return it_; }
constexpr BidiIter const & base_reference() const noexcept
{
return it_;
}
template<typename BidiIter2>
friend struct reverse_iterator;
BidiIter it_;
};
template<typename BidiIter>
constexpr auto operator==(
reverse_iterator<BidiIter> lhs,
reverse_iterator<BidiIter>
rhs) noexcept(noexcept(lhs.base() == rhs.base()))
-> decltype(rhs.base() == lhs.base())
{
return lhs.base() == rhs.base();
}
template<typename BidiIter1, typename BidiIter2>
constexpr auto operator==(
reverse_iterator<BidiIter1> lhs,
reverse_iterator<BidiIter2>
rhs) noexcept(noexcept(lhs.base() == rhs.base()))
-> decltype(rhs.base() == lhs.base())
{
return lhs.base() == rhs.base();
}
/** Makes a `reverse_iterator<BidiIter>` from an iterator of type
`BidiIter`. */
template<typename BidiIter>
auto make_reverse_iterator(BidiIter it)
{
return reverse_iterator<BidiIter>(it);
}
}}}
#if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
namespace boost::parser::detail { namespace stl_interfaces { BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V2 {
/** A template alias for `std::reverse_iterator`. This only exists to
make migration from Boost.STLInterfaces to C++20 easier; switch to the
one in `std` as soon as you can. */
template<typename BidiIter>
using reverse_iterator = std::reverse_iterator<BidiIter>;
/** Makes a `reverse_iterator<BidiIter>` from an iterator of type
`BidiIter`. This only exists to make migration from
Boost.STLInterfaces to C++20 easier; switch to the one in `std` as
soon as you can. */
template<typename BidiIter>
auto make_reverse_iterator(BidiIter it)
{
return reverse_iterator<BidiIter>(it);
}
}}}
namespace boost::parser::detail { namespace stl_interfaces { BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V3 {
/** A template alias for `std::reverse_iterator`. This only exists to
make migration from Boost.STLInterfaces to C++20 easier; switch to the
one in `std` as soon as you can. */
template<typename BidiIter>
using reverse_iterator = std::reverse_iterator<BidiIter>;
/** Makes a `reverse_iterator<BidiIter>` from an iterator of type
`BidiIter`. This only exists to make migration from
Boost.STLInterfaces to C++20 easier; switch to the one in `std` as
soon as you can. */
template<typename BidiIter>
auto make_reverse_iterator(BidiIter it)
{
return reverse_iterator<BidiIter>(it);
}
}}}
#endif
#endif

View File

@@ -1,318 +0,0 @@
// Copyright (C) 2022 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_STL_INTERFACES_VIEW_ADAPTOR_HPP
#define BOOST_PARSER_DETAIL_STL_INTERFACES_VIEW_ADAPTOR_HPP
#include <boost/parser/detail/stl_interfaces/config.hpp>
#include <boost/parser/detail/stl_interfaces/detail/view_closure.hpp>
#include <boost/parser/detail/detection.hpp>
#include <tuple>
#include <type_traits>
#if !defined(BOOST_STL_INTERFACES_DOXYGEN)
#if defined(__cpp_lib_ranges) && 202202L <= __cpp_lib_ranges
#define BOOST_PARSER_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE 1
#else
#define BOOST_PARSER_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE 0
#endif
#if !BOOST_PARSER_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE && \
BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS && defined(__GNUC__) && 12 <= __GNUC__
#define BOOST_PARSER_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE 1
#else
#define BOOST_PARSER_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE 0
#endif
#if !BOOST_PARSER_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE && \
defined(_MSC_VER) && _MSC_VER <= 1929
#define BOOST_PARSER_NEED_VS_COMPATIBLE_RANGE_ADAPTOR_CLOSURE 1
#else
#define BOOST_PARSER_NEED_VS_COMPATIBLE_RANGE_ADAPTOR_CLOSURE 0
#endif
#if !BOOST_PARSER_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE && \
!BOOST_PARSER_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE && \
!BOOST_PARSER_NEED_VS_COMPATIBLE_RANGE_ADAPTOR_CLOSURE
#define BOOST_PARSER_DEFINE_CUSTOM_RANGE_ADAPTOR_CLOSURE 1
#else
#define BOOST_PARSER_DEFINE_CUSTOM_RANGE_ADAPTOR_CLOSURE 0
#endif
#endif
namespace boost::parser::detail { namespace stl_interfaces {
namespace detail {
template<typename F, typename... Args>
using invocable_expr =
decltype(std::declval<F>()(std::declval<Args>()...));
template<typename F, typename... Args>
constexpr bool is_invocable_v =
is_detected_v<invocable_expr, F, Args...>;
template<typename Func, typename... CapturedArgs>
struct bind_back_t
{
static_assert(std::is_move_constructible<Func>::value, "");
#if defined(__cpp_fold_expressions)
static_assert(
(std::is_move_constructible<CapturedArgs>::value && ...), "");
#endif
template<typename F, typename... Args>
explicit constexpr bind_back_t(int, F && f, Args &&... args) :
f_((F &&) f), bound_args_((Args &&) args...)
{
static_assert(sizeof...(Args) == sizeof...(CapturedArgs), "");
}
template<typename... Args>
constexpr decltype(auto) operator()(Args &&... args) &
{
return call_impl(*this, indices(), (Args &&) args...);
}
template<typename... Args>
constexpr decltype(auto) operator()(Args &&... args) const &
{
return call_impl(*this, indices(), (Args &&) args...);
}
template<typename... Args>
constexpr decltype(auto) operator()(Args &&... args) &&
{
return call_impl(
std::move(*this), indices(), (Args &&) args...);
}
template<typename... Args>
constexpr decltype(auto) operator()(Args &&... args) const &&
{
return call_impl(
std::move(*this), indices(), (Args &&) args...);
}
private:
using indices = std::index_sequence_for<CapturedArgs...>;
template<typename T, size_t... I, typename... Args>
static constexpr decltype(auto)
call_impl(T && this_, std::index_sequence<I...>, Args &&... args)
{
return ((T &&) this_)
.f_((Args &&) args...,
std::get<I>(((T &&) this_).bound_args_)...);
}
Func f_;
std::tuple<CapturedArgs...> bound_args_;
};
template<typename Func, typename... Args>
using bind_back_result =
bind_back_t<std::decay_t<Func>, std::decay_t<Args>...>;
}
/** An implementation of `std::bind_back()` from C++23. */
template<typename Func, typename... Args>
constexpr auto bind_back(Func && f, Args &&... args)
{
return detail::bind_back_result<Func, Args...>(
0, (Func &&) f, (Args &&) args...);
}
#if BOOST_PARSER_DEFINE_CUSTOM_RANGE_ADAPTOR_CLOSURE || \
defined(BOOST_STL_INTERFACES_DOXYGEN)
/** A backwards-compatible implementation of C++23's
`std::ranges::range_adaptor_closure`. `range_adaptor_closure` may be
a struct template or may be an alias, as required to maintain
compatability with the standard library's view adaptors. */
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<typename D>
requires std::is_class_v<D> && std::same_as<D, std::remove_cv_t<D>>
#else
template<
typename D,
typename Enable = std::enable_if_t<
std::is_class<D>::value &&
std::is_same<D, std::remove_cv_t<D>>::value>>
#endif
struct range_adaptor_closure;
namespace detail {
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<typename T>
concept range_adaptor_closure_ = std::derived_from<
std::remove_cvref_t<T>,
range_adaptor_closure<std::remove_cvref_t<T>>>;
#else
template<typename T>
using range_adaptor_closure_tag_expr = typename range_adaptor_closure<
T>::inheritance_tag_with_an_unlikely_name_;
template<typename T>
constexpr bool range_adaptor_closure_ =
is_detected_v<range_adaptor_closure_tag_expr, remove_cvref_t<T>>;
#endif
}
#endif
#if BOOST_PARSER_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE
template<typename D>
using range_adaptor_closure = std::ranges::range_adaptor_closure<D>;
#elif BOOST_PARSER_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE
template<typename D>
using range_adaptor_closure = std::views::__adaptor::_RangeAdaptorClosure;
#elif BOOST_PARSER_NEED_VS_COMPATIBLE_RANGE_ADAPTOR_CLOSURE
template<typename D>
using range_adaptor_closure = detail::pipeable<D>;
#else
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<typename D>
requires std::is_class_v<D> && std::same_as<D, std::remove_cv_t<D>>
#else
template<typename D, typename>
#endif
struct range_adaptor_closure
{
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<typename T>
requires std::invocable<D, T>
#else
template<
typename T,
typename Enable = std::enable_if_t<detail::is_invocable_v<D, T>>>
#endif
[[nodiscard]] friend constexpr decltype(auto) operator|(T && t, D && d)
{
return std::move(d)((T &&) t);
}
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<typename T>
requires std::invocable<D const &, T>
#else
template<
typename T,
typename Enable =
std::enable_if_t<detail::is_invocable_v<D const &, T>>>
#endif
[[nodiscard]] friend constexpr decltype(auto)
operator|(T && t, D const & d)
{
return d((T &&) t);
}
using inheritance_tag_with_an_unlikely_name_ = int;
};
#endif
//[closure_defn
/** An invocable consisting of a contained invocable `f`. Calling
`operator()` with some argument `t` calls `f(t)` and returns the
result. This type is typically used to capture a the result of a call
to `bind_back()`. */
template<typename F>
struct closure : range_adaptor_closure<closure<F>>
{
constexpr closure(F f) : f_(f) {}
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<typename T>
requires std::invocable<F const &, T>
#else
template<
typename T,
typename Enable =
std::enable_if_t<detail::is_invocable_v<F const &, T>>>
#endif
constexpr decltype(auto) operator()(T && t) const
{
return f_((T &&) t);
}
private:
F f_;
};
//]
namespace detail {
#if !BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
template<typename F, bool Invocable, typename... Args>
struct adaptor_impl
{
static constexpr decltype(auto) call(F const & f, Args &&... args)
{
return f((Args &&) args...);
}
};
template<typename F, typename... Args>
struct adaptor_impl<F, false, Args...>
{
static constexpr auto call(F const & f, Args &&... args)
{
using closure_func =
std::decay_t<decltype(stl_interfaces::bind_back(
f, (Args &&) args...))>;
return closure<closure_func>(
stl_interfaces::bind_back(f, (Args &&) args...));
}
};
#endif
}
//[adaptor_defn
/** Adapts an invocable `f` as a view adaptor. Calling
`operator(args...)` will either: call `f(args...)` and return the
result, if `f(args...)` is well-formed; or return
`closure(stl_interfaces::bind_back(f, args...))` otherwise. */
template<typename F>
struct adaptor
{
constexpr adaptor(F f) : f_(f) {}
// clang-format off
template<typename... Args>
constexpr auto operator()(Args &&... args) const
// clang-format on
{
#if BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
if constexpr (std::is_invocable_v<F const &, Args...>) {
return f((Args &&) args...);
} else {
return closure(
stl_interfaces::bind_back(f_, (Args &&) args...));
}
#else
return detail::adaptor_impl<
F const &,
detail::is_invocable_v<F const &, Args...>,
Args...>::call(f_, (Args &&) args...);
#endif
}
private:
F f_;
};
//]
}}
#endif

View File

@@ -1,228 +0,0 @@
// Copyright (C) 2019 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_STL_INTERFACES_VIEW_INTERFACE_HPP
#define BOOST_PARSER_DETAIL_STL_INTERFACES_VIEW_INTERFACE_HPP
#include <boost/parser/detail/stl_interfaces/fwd.hpp>
namespace boost::parser::detail { namespace stl_interfaces { BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V1 {
/** A CRTP template that one may derive from to make it easier to define
`std::ranges::view`-like types with a container-like interface. This
is a pre-C++20 version of C++20's `view_interface` (see
[view.interface] in the C++ standard).
The template parameter `D` for `view_interface` may be an incomplete
type. Before any member of the resulting specialization of
`view_interface` other than special member functions is referenced,
`D` shall be complete, and model both
`std::derived_from<view_interface<D>>` and `std::view`. */
template<
typename Derived,
element_layout Contiguity = element_layout::discontiguous
#ifndef BOOST_STL_INTERFACES_DOXYGEN
,
typename E = std::enable_if_t<
std::is_class<Derived>::value &&
std::is_same<Derived, std::remove_cv_t<Derived>>::value>
#endif
>
struct view_interface;
namespace v1_dtl {
template<typename D, element_layout Contiguity>
void derived_view(view_interface<D, Contiguity> const &);
}
template<
typename Derived,
element_layout Contiguity
#ifndef BOOST_STL_INTERFACES_DOXYGEN
,
typename E
#endif
>
struct view_interface
{
#ifndef BOOST_STL_INTERFACES_DOXYGEN
private:
constexpr Derived & derived() noexcept
{
return static_cast<Derived &>(*this);
}
constexpr const Derived & derived() const noexcept
{
return static_cast<Derived const &>(*this);
}
#endif
public:
template<typename D = Derived>
constexpr auto empty() noexcept(
noexcept(std::declval<D &>().begin() == std::declval<D &>().end()))
-> decltype(
std::declval<D &>().begin() == std::declval<D &>().end())
{
return derived().begin() == derived().end();
}
template<typename D = Derived>
constexpr auto empty() const noexcept(noexcept(
std::declval<D const &>().begin() ==
std::declval<D const &>().end()))
-> decltype(
std::declval<D const &>().begin() ==
std::declval<D const &>().end())
{
return derived().begin() == derived().end();
}
template<
typename D = Derived,
typename R = decltype(std::declval<D &>().empty())>
constexpr explicit
operator bool() noexcept(noexcept(std::declval<D &>().empty()))
{
return !derived().empty();
}
template<
typename D = Derived,
typename R = decltype(std::declval<D const &>().empty())>
constexpr explicit operator bool() const
noexcept(noexcept(std::declval<D const &>().empty()))
{
return !derived().empty();
}
template<
typename D = Derived,
element_layout C = Contiguity,
typename Enable = std::enable_if_t<C == element_layout::contiguous>>
constexpr auto data() noexcept(noexcept(std::declval<D &>().begin()))
-> decltype(std::addressof(*std::declval<D &>().begin()))
{
return std::addressof(*derived().begin());
}
template<
typename D = Derived,
element_layout C = Contiguity,
typename Enable = std::enable_if_t<C == element_layout::contiguous>>
constexpr auto data() const
noexcept(noexcept(std::declval<D const &>().begin()))
-> decltype(std::addressof(*std::declval<D const &>().begin()))
{
return std::addressof(*derived().begin());
}
template<typename D = Derived>
constexpr auto size() noexcept(
noexcept(std::declval<D &>().end() - std::declval<D &>().begin()))
-> decltype(std::declval<D &>().end() - std::declval<D &>().begin())
{
return derived().end() - derived().begin();
}
template<typename D = Derived>
constexpr auto size() const noexcept(noexcept(
std::declval<D const &>().end() -
std::declval<D const &>().begin()))
-> decltype(
std::declval<D const &>().end() -
std::declval<D const &>().begin())
{
return derived().end() - derived().begin();
}
template<typename D = Derived>
constexpr auto front() noexcept(noexcept(*std::declval<D &>().begin()))
-> decltype(*std::declval<D &>().begin())
{
return *derived().begin();
}
template<typename D = Derived>
constexpr auto front() const
noexcept(noexcept(*std::declval<D const &>().begin()))
-> decltype(*std::declval<D const &>().begin())
{
return *derived().begin();
}
template<
typename D = Derived,
typename Enable = std::enable_if_t<
v1_dtl::decrementable_sentinel<D>::value &&
v1_dtl::common_range<D>::value>>
constexpr auto
back() noexcept(noexcept(*std::prev(std::declval<D &>().end())))
-> decltype(*std::prev(std::declval<D &>().end()))
{
return *std::prev(derived().end());
}
template<
typename D = Derived,
typename Enable = std::enable_if_t<
v1_dtl::decrementable_sentinel<D>::value &&
v1_dtl::common_range<D>::value>>
constexpr auto back() const
noexcept(noexcept(*std::prev(std::declval<D const &>().end())))
-> decltype(*std::prev(std::declval<D const &>().end()))
{
return *std::prev(derived().end());
}
template<typename D = Derived>
constexpr auto operator[](v1_dtl::range_difference_t<D> n) noexcept(
noexcept(std::declval<D &>().begin()[n]))
-> decltype(std::declval<D &>().begin()[n])
{
return derived().begin()[n];
}
template<typename D = Derived>
constexpr auto operator[](v1_dtl::range_difference_t<D> n) const
noexcept(noexcept(std::declval<D const &>().begin()[n]))
-> decltype(std::declval<D const &>().begin()[n])
{
return derived().begin()[n];
}
};
/** Implementation of `operator!=()` for all views derived from
`view_interface`. */
template<typename ViewInterface>
constexpr auto operator!=(ViewInterface lhs, ViewInterface rhs) noexcept(
noexcept(lhs == rhs))
-> decltype(v1_dtl::derived_view(lhs), !(lhs == rhs))
{
return !(lhs == rhs);
}
}}}
#if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_PARSER_DETAIL_STL_INTERFACES_USE_CONCEPTS
namespace boost::parser::detail { namespace stl_interfaces { BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V2 {
/** A template alias for `std::ranges::view_interface`. This only exists
to make migration from Boost.STLInterfaces to C++20 easier; switch to
the one in `std` as soon as you can. */
template<typename D, element_layout = element_layout::discontiguous>
using view_interface = std::ranges::view_interface<D>;
}}}
namespace boost::parser::detail { namespace stl_interfaces { BOOST_PARSER_DETAIL_STL_INTERFACES_NAMESPACE_V3 {
/** A template alias for `std::ranges::view_interface`. This only exists
to make migration from Boost.STLInterfaces to C++20 easier; switch to
the one in `std` as soon as you can. */
template<typename D, element_layout = element_layout::discontiguous>
using view_interface = std::ranges::view_interface<D>;
}}}
#endif
#endif

View File

@@ -1,387 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_ALGORITHM_HPP
#define BOOST_PARSER_DETAIL_TEXT_ALGORITHM_HPP
#include <boost/parser/detail/text/config.hpp>
#include <boost/parser/detail/text/detail/algorithm.hpp>
#include <boost/parser/detail/text/detail/sentinel_tag.hpp>
#include <boost/parser/detail/stl_interfaces/view_interface.hpp>
#include <cstddef>
#include <iterator>
#include <utility>
namespace boost::parser::detail { namespace text {
namespace detail {
template<typename Iter>
std::ptrdiff_t distance(Iter first, Iter last, non_sentinel_tag)
{
return std::distance(first, last);
}
template<typename Iter, typename Sentinel>
std::ptrdiff_t distance(Iter first, Sentinel last, sentinel_tag)
{
std::ptrdiff_t retval = 0;
while (first != last) {
++retval;
++first;
}
return retval;
}
}
/** Range-friendly version of `std::distance()`, taking an iterator and a
sentinel. */
template<typename Iter, typename Sentinel>
std::ptrdiff_t distance(Iter first, Sentinel last)
{
return detail::distance(
first,
last,
typename std::conditional<
std::is_same<Iter, Sentinel>::value,
detail::non_sentinel_tag,
detail::sentinel_tag>::type());
}
/** Range-friendly version of `std::find()`, taking an iterator and a
sentinel. */
template<typename BidiIter, typename Sentinel, typename T>
BidiIter find(BidiIter first, Sentinel last, T const & x)
{
while (first != last) {
if (*first == x)
return first;
++first;
}
return first;
}
/** A range-friendly compliment to `std::find()`; returns an iterator to
the first element not equal to `x`. */
template<typename BidiIter, typename Sentinel, typename T>
BidiIter find_not(BidiIter first, Sentinel last, T const & x)
{
while (first != last) {
if (*first != x)
return first;
++first;
}
return first;
}
/** Range-friendly version of `std::find_if()`, taking an iterator and a
sentinel. */
template<typename BidiIter, typename Sentinel, typename Pred>
BidiIter find_if(BidiIter first, Sentinel last, Pred p)
{
while (first != last) {
if (p(*first))
return first;
++first;
}
return first;
}
/** Range-friendly version of `std::find_if_not()`, taking an iterator and
a sentinel. */
template<typename BidiIter, typename Sentinel, typename Pred>
BidiIter find_if_not(BidiIter first, Sentinel last, Pred p)
{
while (first != last) {
if (!p(*first))
return first;
++first;
}
return first;
}
/** Analogue of `std::find()` that finds the last value in `[first, last)`
equal to `x`. */
template<typename BidiIter, typename T>
BidiIter find_backward(BidiIter first, BidiIter last, T const & x)
{
auto it = last;
while (it != first) {
if (*--it == x)
return it;
}
return last;
}
/** Analogue of `std::find()` that finds the last value in `[first, last)`
not equal to `x`. */
template<typename BidiIter, typename T>
BidiIter find_not_backward(BidiIter first, BidiIter last, T const & x)
{
auto it = last;
while (it != first) {
if (*--it != x)
return it;
}
return last;
}
/** Analogue of `std::find()` that finds the last value `v` in `[first,
last)` for which `p(v)` is true. */
template<typename BidiIter, typename Pred>
BidiIter find_if_backward(BidiIter first, BidiIter last, Pred p)
{
auto it = last;
while (it != first) {
if (p(*--it))
return it;
}
return last;
}
/** Analogue of `std::find()` that finds the last value `v` in `[first,
last)` for which `p(v)` is false. */
template<typename BidiIter, typename Pred>
BidiIter find_if_not_backward(BidiIter first, BidiIter last, Pred p)
{
auto it = last;
while (it != first) {
if (!p(*--it))
return it;
}
return last;
}
/** A utility range type returned by `foreach_subrange*()`. */
template<typename Iter, typename Sentinel = Iter>
using foreach_subrange_range =
BOOST_PARSER_DETAIL_TEXT_SUBRANGE<Iter, Sentinel>;
/** Calls `f(sub)` for each subrange `sub` in `[first, last)`. A subrange
is a contiguous subsequence of elements that each compares equal to
the first element of the subsequence. Subranges passed to `f` are
non-overlapping. */
template<typename FwdIter, typename Sentinel, typename Func>
Func foreach_subrange(FwdIter first, Sentinel last, Func f)
{
while (first != last) {
auto const & x = *first;
auto const next = boost::parser::detail::text::find_not(first, last, x);
if (first != next) {
f(boost::parser::detail::text::foreach_subrange_range<FwdIter, Sentinel>(
first, next));
}
first = next;
}
return f;
}
/** Calls `f(sub)` for each subrange `sub` in `[first, last)`. A subrange
is a contiguous subsequence of elements that for each element `e`,
`proj(e)` each compares equal to `proj()` of the first element of the
subsequence. Subranges passed to `f` are non-overlapping. */
template<typename FwdIter, typename Sentinel, typename Func, typename Proj>
Func foreach_subrange(FwdIter first, Sentinel last, Func f, Proj proj)
{
using value_type = typename std::iterator_traits<FwdIter>::value_type;
while (first != last) {
auto const & x = proj(*first);
auto const next = boost::parser::detail::text::find_if_not(
first, last, [&x, proj](const value_type & element) {
return proj(element) == x;
});
if (first != next) {
f(boost::parser::detail::text::foreach_subrange_range<FwdIter, Sentinel>(
first, next));
}
first = next;
}
return f;
}
/** Calls `f(sub)` for each subrange `sub` in `[first, last)`. A subrange
is a contiguous subsequence of elements, each of which is equal to
`x`. Subranges passed to `f` are non-overlapping. */
template<typename FwdIter, typename Sentinel, typename T, typename Func>
Func foreach_subrange_of(FwdIter first, Sentinel last, T const & x, Func f)
{
while (first != last) {
first = boost::parser::detail::text::find(first, last, x);
auto const next = boost::parser::detail::text::find_not(first, last, x);
if (first != next) {
f(boost::parser::detail::text::foreach_subrange_range<FwdIter, Sentinel>(
first, next));
}
first = next;
}
return f;
}
/** Calls `f(sub)` for each subrange `sub` in `[first, last)`. A subrange
is a contiguous subsequence of elements `ei` for which `p(ei)` is
true. Subranges passed to `f` are non-overlapping. */
template<typename FwdIter, typename Sentinel, typename Pred, typename Func>
Func foreach_subrange_if(FwdIter first, Sentinel last, Pred p, Func f)
{
while (first != last) {
first = boost::parser::detail::text::find_if(first, last, p);
auto const next = boost::parser::detail::text::find_if_not(first, last, p);
if (first != next) {
f(boost::parser::detail::text::foreach_subrange_range<FwdIter, Sentinel>(
first, next));
}
first = next;
}
return f;
}
/** Sentinel-friendly version of `std::all_of()`. */
template<typename Iter, typename Sentinel, typename Pred>
bool all_of(Iter first, Sentinel last, Pred p)
{
for (; first != last; ++first) {
if (!p(*first))
return false;
}
return true;
}
/** Sentinel-friendly version of `std::equal()`. */
template<
typename Iter1,
typename Sentinel1,
typename Iter2,
typename Sentinel2>
bool equal(Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2)
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
if (*first1 != *first2)
return false;
}
return first1 == last1 && first2 == last2;
}
/** Sentinel-friendly version of `std::mismatch()`. */
template<
typename Iter1,
typename Sentinel1,
typename Iter2,
typename Sentinel2>
std::pair<Iter1, Iter2>
mismatch(Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2)
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
if (*first1 != *first2)
break;
}
return {first1, first2};
}
/** Sentinel-friendly version of
`std::lexicographical_compare_three_way()`, except that it returns an
`int` instead of a `std::strong_ordering`. */
template<
typename Iter1,
typename Sentinel1,
typename Iter2,
typename Sentinel2>
int lexicographical_compare_three_way(
Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2)
{
auto const iters = boost::parser::detail::text::mismatch(first1, last1, first2, last2);
if (iters.first == last1) {
if (iters.second == last2)
return 0;
else
return -1;
} else if (iters.second == last2) {
return 1;
} else if (*iters.first < *iters.second) {
return -1;
} else {
return 1;
}
}
/** The view type returned by `boost::parser::detail::text::search()`. */
template<typename Iter>
using search_result = BOOST_PARSER_DETAIL_TEXT_SUBRANGE<Iter>;
/** Sentinel-friendly version of `std::search()`. */
template<
typename Iter1,
typename Sentinel1,
typename Iter2,
typename Sentinel2>
search_result<Iter1>
search(Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2)
{
if (first1 == last1 || first2 == last2)
return {first1, first1};
if (detail::next(first2) == last2) {
auto const it = parser::detail::text::find(first1, last1, *first2);
return {it, detail::next(it)};
}
auto it = first1;
for (;;) {
first1 = parser::detail::text::find(first1, last1, *first2);
if (first1 == last1)
return {first1, first1};
auto it2 = detail::next(first2);
it = first1;
if (++it == last1)
return {it, it};
while (*it == *it2) {
if (++it2 == last2)
return {first1, ++it};
if (++it == last1)
return {it, it};
}
++first1;
}
return {first1, first1};
}
/** Sentinel-friendly version of `std::find_first_of()`. */
template<
typename Iter1,
typename Sentinel1,
typename Iter2,
typename Sentinel2,
typename Pred>
Iter1 find_first_of(
Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2, Pred pred)
{
for (; first1 != last1; ++first1) {
for (auto it = first2; it != last2; ++it) {
if (pred(*first1, *it))
return first1;
}
}
return first1;
}
}}
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
namespace std::ranges {
template<typename Iter, typename Sentinel>
inline constexpr bool enable_borrowed_range<
boost::parser::detail::text::foreach_subrange_range<Iter, Sentinel>> = true;
}
#endif
#endif

View File

@@ -1,269 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_CONCEPTS_HPP
#define BOOST_PARSER_DETAIL_TEXT_CONCEPTS_HPP
#include <boost/parser/detail/text/config.hpp>
#include <boost/parser/detail/text/utf.hpp>
#include <boost/parser/detail/text/detail/begin_end.hpp>
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
#include <ranges>
#include <string_view>
namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V2 {
//[ concepts_concepts
#ifdef _MSC_VER
inline constexpr format wchar_t_format = format::utf16;
#else
inline constexpr format wchar_t_format = format::utf32;
#endif
template<typename T, format F>
concept code_unit = (std::same_as<T, char8_t> && F == format::utf8) ||
(std::same_as<T, char16_t> && F == format::utf16) ||
(std::same_as<T, char32_t> && F == format::utf32) ||
(std::same_as<T, char> && F == format::utf8) ||
(std::same_as<T, wchar_t> && F == wchar_t_format);
template<typename T>
concept utf8_code_unit = code_unit<T, format::utf8>;
template<typename T>
concept utf16_code_unit = code_unit<T, format::utf16>;
template<typename T>
concept utf32_code_unit = code_unit<T, format::utf32>;
template<typename T, format F>
concept code_unit_iter =
std::input_iterator<T> && code_unit<std::iter_value_t<T>, F>;
template<typename T>
concept utf_code_unit =
utf8_code_unit<T> || utf16_code_unit<T> || utf32_code_unit<T>;
template<typename T, format F>
concept code_unit_pointer =
std::is_pointer_v<T> && code_unit<std::iter_value_t<T>, F>;
template<typename T, format F>
concept code_unit_range = std::ranges::input_range<T> &&
code_unit<std::ranges::range_value_t<T>, F>;
template<typename T, format F>
concept contiguous_code_unit_range = std::ranges::contiguous_range<T> &&
code_unit<std::ranges::range_value_t<T>, F>;
template<typename T>
concept utf8_iter = code_unit_iter<T, format::utf8>;
template<typename T>
concept utf8_pointer = code_unit_pointer<T, format::utf8>;
template<typename T>
concept utf8_range = code_unit_range<T, format::utf8>;
template<typename T>
concept contiguous_utf8_range = contiguous_code_unit_range<T, format::utf8>;
template<typename T>
concept utf16_iter = code_unit_iter<T, format::utf16>;
template<typename T>
concept utf16_pointer = code_unit_pointer<T, format::utf16>;
template<typename T>
concept utf16_range = code_unit_range<T, format::utf16>;
template<typename T>
concept contiguous_utf16_range =
contiguous_code_unit_range<T, format::utf16>;
template<typename T>
concept utf32_iter = code_unit_iter<T, format::utf32>;
template<typename T>
concept utf32_pointer = code_unit_pointer<T, format::utf32>;
template<typename T>
concept utf32_range = code_unit_range<T, format::utf32>;
template<typename T>
concept contiguous_utf32_range =
contiguous_code_unit_range<T, format::utf32>;
template<typename T>
concept code_point = utf32_code_unit<T>;
template<typename T>
concept code_point_iter = utf32_iter<T>;
template<typename T>
concept code_point_range = utf32_range<T>;
template<typename T>
concept utf_iter = utf8_iter<T> || utf16_iter<T> || utf32_iter<T>;
template<typename T>
concept utf_pointer =
utf8_pointer<T> || utf16_pointer<T> || utf32_pointer<T>;
template<typename T>
concept utf_range = utf8_range<T> || utf16_range<T> || utf32_range<T>;
template<typename T>
concept grapheme_iter =
// clang-format off
std::input_iterator<T> &&
code_point_range<std::iter_reference_t<T>> &&
requires(T t) {
{ t.base() } -> code_point_iter;
// clang-format on
};
template<typename T>
concept grapheme_range = std::ranges::input_range<T> &&
grapheme_iter<std::ranges::iterator_t<T>>;
template<typename R>
using code_point_iterator_t = decltype(std::declval<R>().begin().base());
template<typename R>
using code_point_sentinel_t = decltype(std::declval<R>().end().base());
template<typename T, format F>
concept grapheme_iter_code_unit =
// clang-format off
grapheme_iter<T> &&
requires(T t) {
{ t.base().base() } -> code_unit_iter<F>;
// clang-format on
};
template<typename T, format F>
concept grapheme_range_code_unit = grapheme_range<T> &&
grapheme_iter_code_unit<std::ranges::iterator_t<T>, F>;
namespace dtl {
template<typename T, class CodeUnit>
concept eraseable_insertable_sized_bidi_range =
// clang-format off
std::ranges::sized_range<T> &&
std::ranges::input_range<T> &&
requires(T t, CodeUnit const * it) {
{ t.erase(t.begin(), t.end()) } ->
std::same_as<std::ranges::iterator_t<T>>;
{ t.insert(t.end(), it, it) } ->
std::same_as<std::ranges::iterator_t<T>>;
};
// clang-format on
}
template<typename T>
concept utf8_string =
// clang-format off
utf8_code_unit<std::ranges::range_value_t<T>> &&
dtl::eraseable_insertable_sized_bidi_range<
T, std::ranges::range_value_t<T>>;
// clang-format on
template<typename T>
concept utf16_string =
// clang-format off
utf16_code_unit<std::ranges::range_value_t<T>> &&
dtl::eraseable_insertable_sized_bidi_range<
T, std::ranges::range_value_t<T>>;
// clang-format on
template<typename T>
concept utf_string = utf8_string<T> || utf16_string<T>;
template<typename T>
// clang-format off
concept transcoding_error_handler = requires(T t, std::string_view msg) {
{ t(msg) } -> std::same_as<char32_t>;
// clang-format on
};
template<typename T>
// clang-format off
concept utf_range_like =
utf_range<std::remove_reference_t<T>> ||
utf_pointer<std::remove_reference_t<T>>;
// clang-format on
template<typename T>
concept utf8_range_like = utf8_code_unit<std::iter_value_t<T>> ||
utf8_pointer<std::remove_reference_t<T>>;
template<typename T>
concept utf16_range_like = utf16_code_unit<std::iter_value_t<T>> ||
utf16_pointer<std::remove_reference_t<T>>;
template<typename T>
concept utf32_range_like = utf32_code_unit<std::iter_value_t<T>> ||
utf32_pointer<std::remove_reference_t<T>>;
//]
// Clang 13 defines __cpp_lib_concepts but not std::indirectly copyable.
#if defined(__clang_major__) && __clang_major__ == 13
template<typename In, typename Out>
// clang-format off
concept indirectly_copyable =
std::indirectly_readable<In> &&
std::indirectly_writable<Out, std::iter_reference_t<In>>;
// clang-format on
#else
template<typename In, typename Out>
concept indirectly_copyable = std::indirectly_copyable<In, Out>;
#endif
}}}
#endif
namespace boost::parser::detail { namespace text { namespace detail {
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<typename T>
using iterator_t = std::ranges::iterator_t<T>;
template<typename T>
using sentinel_t = std::ranges::sentinel_t<T>;
template<typename T>
using iter_value_t = std::iter_value_t<T>;
template<typename T>
using iter_reference_t = std::iter_reference_t<T>;
template<typename T>
using range_value_t = std::ranges::range_value_t<T>;
template<typename T>
using range_reference_t = std::ranges::range_reference_t<T>;
template<typename T>
using range_difference_t = std::ranges::range_difference_t<T>;
#else
template<typename T>
using iterator_t = decltype(detail::begin(std::declval<T &>()));
template<typename T>
using sentinel_t = decltype(detail::end(std::declval<T &>()));
template<typename T>
using iter_value_t = typename std::iterator_traits<T>::value_type;
template<typename T>
using iter_reference_t = decltype(*std::declval<T &>());
template<typename T>
using range_value_t = iter_value_t<iterator_t<T>>;
template<typename T>
using range_reference_t = iter_reference_t<iterator_t<T>>;
template<typename T>
using range_difference_t = std::ptrdiff_t;
template<typename T>
constexpr bool code_unit_v =
#if defined(__cpp_char8_t)
std::is_same_v<T, char8_t> ||
#endif
std::is_same_v<T, char16_t> || std::is_same_v<T, char32_t> ||
std::is_same_v<T, char> || std::is_same_v<T, wchar_t>;
#endif
}}}
#endif

View File

@@ -1,66 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_CONFIG_HPP
#define BOOST_PARSER_DETAIL_TEXT_CONFIG_HPP
#include <boost/parser/config.hpp>
// Included for definition of __cpp_lib_concepts.
#include <iterator>
#if !BOOST_PARSER_USE_CONCEPTS || defined(_MSC_VER)
# define BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS 0
#else
# define BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS 1
#endif
// GCC 12 claims to support 201907L <= __cpp_deduction_guides, but does not.
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS && defined(__cpp_deduction_guides) && \
201907L <= __cpp_deduction_guides && (!defined(__GNUC__) || 13 <= __GNUC__)
#define BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD 1
#else
#define BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD 0
#endif
#if defined(__cpp_lib_ranges)
namespace boost::parser::detail { namespace text { namespace detail {
inline constexpr auto begin = std::ranges::begin;
inline constexpr auto end = std::ranges::end;
}}}
#else
#include <boost/parser/detail/text/detail/begin_end.hpp>
#endif
#if defined(__cpp_lib_ranges)
# define BOOST_PARSER_DETAIL_TEXT_SUBRANGE std::ranges::subrange
#else
# include <boost/parser/subrange.hpp>
# define BOOST_PARSER_DETAIL_TEXT_SUBRANGE boost::parser::subrange
#endif
namespace boost::parser::detail { namespace text {
#if defined(__cpp_char8_t)
using char8_type = char8_t;
#else
using char8_type = char;
#endif
}}
// The inline namespaces v1 and v2 represent pre- and post-C++20. v1 is
// inline for standards before C++20, and v2 is inline for C++20 and later.
// Note that this only applies to code for which a v2 namespace alternative
// exists. Some instances of the v1 namespace may still be inline, if there
// is no v2 version of its contents.
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
# define BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V1 namespace v1
# define BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V2 inline namespace v2
#else
# define BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V1 inline namespace v1
# define BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V2 namespace v2
#endif
#endif

View File

@@ -1,917 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_DETAIL_ALGORITHM_HPP
#define BOOST_PARSER_DETAIL_TEXT_DETAIL_ALGORITHM_HPP
#include <boost/parser/detail/text/concepts.hpp>
#include <boost/parser/detail/detection.hpp>
#include <boost/parser/detail/text/detail/iterator.hpp>
#include <numeric>
#include <type_traits>
#include <utility>
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
#include <ranges>
#endif
#include <cstdint>
namespace boost::parser::detail { namespace text { namespace detail {
template<typename I>
auto prev(I it)
{
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
return std::ranges::prev(it);
#else
return std::prev(it);
#endif
}
template<typename I>
auto next(I it)
{
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
return std::ranges::next(it);
#else
return std::next(it);
#endif
}
template<typename T>
using remove_cv_ref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
// A grapheme_range that has a sentinel type that is not an iterator, but
// that is comparable with T's interator type.
template<typename T>
concept cp_sentinel_gr_rng =
// clang-format off
grapheme_range<T> &&
!grapheme_iter<sentinel_t<T>> &&
requires(iterator_t<T> first, sentinel_t<T> last) {
{ first.base() == last } -> std::convertible_to<bool>;
// clang-format on
};
template<typename T>
using gr_rng_cp_iter_t = decltype(std::declval<iterator_t<T>>().base());
template<typename T>
using gr_rng_cp_sent_t = std::conditional_t<
cp_sentinel_gr_rng<T>,
sentinel_t<T>,
gr_rng_cp_iter_t<T>>;
#else
template<typename T>
using has_base = decltype(std::declval<T>().base());
template<typename T>
using sentinel_comparable_to_iter_base =
decltype(std::declval<T>().begin().base() == std::declval<T>().end());
// A grapheme_range that has a sentinel type that is not an iterator, but
// that is comparable with T's interator type.
template<
typename T,
bool IsIt = is_detected_v<has_base, iterator_t<T>> &&
!is_detected_v<has_base, sentinel_t<T>> &&
is_detected_v<sentinel_comparable_to_iter_base, T>>
constexpr bool is_cp_sentinel_gr_rng_v = false;
template<typename T>
constexpr bool is_cp_sentinel_gr_rng_v<T, true> = true;
template<typename T>
using gr_rng_cp_iter_t =
decltype(detail::begin(std::declval<T &>()).base());
template<typename T>
using gr_rng_cp_sent_t = std::conditional_t<
is_cp_sentinel_gr_rng_v<T>,
sentinel_t<T>,
gr_rng_cp_iter_t<T>>;
#endif
template<typename T>
using has_begin = decltype(*detail::begin(std::declval<T &>()));
template<typename T>
using has_end = decltype(*detail::end(std::declval<T &>()));
template<typename T>
using value_type_ = typename std::remove_cv<
typename std::remove_reference<typename T::value_type>::type>::type;
template<typename T>
using nonpointer_iterator_category_ =
typename T::iterator::iterator_category;
template<typename T>
using iterator_pointer_expr = std::is_pointer<typename T::iterator>;
template<typename T>
using iterator_category_ = typename std::conditional<
detected_or_t<std::false_type, iterator_pointer_expr>::value,
std::random_access_iterator_tag,
detected_t<nonpointer_iterator_category_, T>>::type;
template<typename T, typename U, int N>
constexpr bool
is_convertible_and_n_bytes_v = std::is_convertible<T, U>::value &&
sizeof(T) == N;
template<typename T>
constexpr bool is_char_iter_v =
std::is_same<char *, typename std::remove_cv<T>::type>::value ||
std::is_same<char const *, typename std::remove_cv<T>::type>::value ||
#if defined(__cpp_char8_t)
std::is_same<char8_t *, typename std::remove_cv<T>::type>::value ||
std::is_same<char8_t const *, typename std::remove_cv<T>::type>::
value ||
#endif
is_convertible_and_n_bytes_v<detected_t<value_type_, T>, char, 1>;
// Needed for detected_or_t.
template<typename T>
using is_char_iter = std::integral_constant<bool, is_char_iter_v<T>>;
template<typename T>
constexpr bool is_char_range_v =
(is_convertible_and_n_bytes_v<
remove_cv_ref_t<detected_t<has_begin, T>>,
char,
1> &&
is_convertible_and_n_bytes_v<
remove_cv_ref_t<detected_t<has_end, T>>,
char,
1>);
template<
typename T,
typename R1,
typename Exclude,
bool R1IsCharRange =
is_char_range_v<R1> && !std::is_same<R1, Exclude>::value>
struct rng_alg_ret
{
};
template<typename T, typename R1, typename Exclude>
struct rng_alg_ret<T, R1, Exclude, true>
{
using type = T;
};
template<typename T, typename R1, typename Exclude = void>
using rng_alg_ret_t = typename rng_alg_ret<T, R1, Exclude>::type;
template<
typename T,
typename R1,
typename R2,
bool R1IsCharRange = is_char_range_v<R1>,
bool R2IsCharRange = is_char_range_v<R2>>
struct rngs_alg_ret
{
};
template<typename T, typename R1, typename R2>
struct rngs_alg_ret<T, R1, R2, true, true>
{
using type = T;
};
template<typename T, typename R1, typename R2>
using rngs_alg_ret_t = typename rngs_alg_ret<T, R1, R2>::type;
template<typename T>
using has_contig_begin = decltype(&*detail::begin(std::declval<T &>()));
template<typename T>
using has_contig_end = decltype(&*detail::end(std::declval<T &>()));
template<typename T>
constexpr bool is_contig_char_range_v =
((std::is_same<
fixup_ptr_t<detected_t<has_contig_begin, T>>,
char const *>::value &&
std::is_same<
fixup_ptr_t<detected_t<has_contig_end, T>>,
char const *>::value)
#if defined(__cpp_char8_t)
|| (std::is_same<
fixup_ptr_t<detected_t<has_contig_begin, T>>,
char8_t const *>::value &&
std::is_same<
fixup_ptr_t<detected_t<has_contig_end, T>>,
char8_t const *>::value)
#endif
) &&
std::is_convertible<
iterator_category_<T>,
std::random_access_iterator_tag>::value;
template<
typename T,
typename R1,
bool R1IsContigCharRange = is_contig_char_range_v<R1>>
struct contig_rng_alg_ret
{
};
template<typename T, typename R1>
struct contig_rng_alg_ret<T, R1, true>
{
using type = T;
};
template<typename T, typename R1>
using contig_rng_alg_ret_t = typename contig_rng_alg_ret<T, R1>::type;
template<
typename T,
typename R1,
typename R2,
bool R1IsContigCharRange = is_contig_char_range_v<R1>,
bool R2IsContigCharRange = is_contig_char_range_v<R2>>
struct contig_rngs_alg_ret
{
};
template<typename T, typename R1, typename R2>
struct contig_rngs_alg_ret<T, R1, R2, true, true>
{
using type = T;
};
template<typename T, typename R1, typename R2>
using contig_rngs_alg_ret_t = typename contig_rngs_alg_ret<T, R1, R2>::type;
template<typename T>
constexpr bool is_char16_range_v =
(is_convertible_and_n_bytes_v<
remove_cv_ref_t<detected_t<has_begin, T>>,
uint16_t,
2> &&
is_convertible_and_n_bytes_v<
remove_cv_ref_t<detected_t<has_end, T>>,
uint16_t,
2>);
template<
typename T,
typename R1,
bool R1IsChar16Range = is_char16_range_v<R1>>
struct rng16_alg_ret
{
};
template<typename T, typename R1>
struct rng16_alg_ret<T, R1, true>
{
using type = T;
};
template<typename T, typename R1>
using rng16_alg_ret_t = typename rng16_alg_ret<T, R1>::type;
template<typename T, typename R1, bool R1IsCharRange = is_char_iter_v<R1>>
struct char_iter_ret
{
};
template<typename T, typename R1>
struct char_iter_ret<T, R1, true>
{
using type = T;
};
template<typename T, typename R1>
using char_iter_ret_t = typename char_iter_ret<T, R1>::type;
template<typename T>
constexpr bool is_code_point_v = std::is_integral<T>::value &&
sizeof(T) == 4;
template<typename T>
using has_deref_and_incr =
std::pair<decltype(*std::declval<T>()), decltype(++std::declval<T>())>;
template<typename T>
constexpr bool is_cp_iter_v =
((std::is_pointer<T>::value &&
is_code_point_v<typename std::remove_cv<
typename std::remove_pointer<T>::type>::type>) ||
(is_detected_v<has_deref_and_incr, T> &&
is_code_point_v<
typename std::remove_cv<detected_t<value_type_, T>>::type>));
template<typename T, typename R1, bool R1IsCPRange = is_cp_iter_v<R1>>
struct cp_iter_ret
{
};
template<typename T, typename R1>
struct cp_iter_ret<T, R1, true>
{
using type = T;
};
template<typename T, typename R1>
using cp_iter_ret_t = typename cp_iter_ret<T, R1>::type;
template<
typename T,
typename R1,
typename R2,
bool R1R2AreCPRanges = is_cp_iter_v<R1> && is_cp_iter_v<R2>>
struct cp_iters_ret
{
};
template<typename T, typename R1, typename R2>
struct cp_iters_ret<T, R1, R2, true>
{
using type = T;
};
template<typename T, typename R1, typename R2>
using cp_iters_ret_t = typename cp_iters_ret<T, R1, R2>::type;
template<typename T>
constexpr bool is_16_code_unit_v = std::is_integral<T>::value &&
sizeof(T) == 2;
template<typename T>
constexpr bool is_16_iter_v =
((std::is_pointer<T>::value &&
is_16_code_unit_v<typename std::remove_cv<
typename std::remove_pointer<T>::type>::type>) ||
(is_detected_v<has_deref_and_incr, T> &&
is_16_code_unit_v<
typename std::remove_cv<detected_t<value_type_, T>>::type>));
template<typename T, typename R1, bool R1IsCPRange = is_16_iter_v<R1>>
struct _16_iter_ret
{
};
template<typename T, typename R1>
struct _16_iter_ret<T, R1, true>
{
using type = T;
};
template<typename T, typename R1>
using _16_iter_ret_t = typename _16_iter_ret<T, R1>::type;
template<typename T>
constexpr bool is_8_code_unit_v = std::is_integral<T>::value &&
sizeof(T) == 1;
template<typename T>
constexpr bool is_8_iter_v =
((std::is_pointer<T>::value &&
is_8_code_unit_v<typename std::remove_cv<
typename std::remove_pointer<T>::type>::type>) ||
(is_detected_v<has_deref_and_incr, T> &&
is_8_code_unit_v<
typename std::remove_cv<detected_t<value_type_, T>>::type>));
template<typename T, typename R1, bool R1IsCPRange = is_8_iter_v<R1>>
struct _8_iter_ret
{
};
template<typename T, typename R1>
struct _8_iter_ret<T, R1, true>
{
using type = T;
};
template<typename T, typename R1>
using _8_iter_ret_t = typename _8_iter_ret<T, R1>::type;
template<typename T, typename U>
using comparable_ = decltype(std::declval<T>() == std::declval<U>());
template<
typename T,
typename CPIter,
typename Sentinel,
bool FIsWordPropFunc = is_cp_iter_v<CPIter> &&
is_detected_v<comparable_, CPIter, Sentinel>>
struct cp_iter_sntl_ret
{
};
template<typename T, typename CPIter, typename Sentinel>
struct cp_iter_sntl_ret<T, CPIter, Sentinel, true>
{
using type = T;
};
template<typename T, typename CPIter, typename Sentinel>
using cp_iter_sntl_ret_t =
typename cp_iter_sntl_ret<T, CPIter, Sentinel>::type;
template<typename T, typename R>
using cp_rng_alg_ret_t =
cp_iter_sntl_ret_t<T, iterator_t<R>, sentinel_t<R>>;
template<
typename T,
typename CPIter1,
typename Sentinel1,
typename CPIter2,
typename Sentinel2,
bool AreCPRanges = is_cp_iter_v<CPIter1> && is_cp_iter_v<CPIter2> &&
is_detected_v<comparable_, CPIter1, Sentinel1> &&
is_detected_v<comparable_, CPIter2, Sentinel2>>
struct cp_iters_sntls_ret
{
};
template<
typename T,
typename CPIter1,
typename Sentinel1,
typename CPIter2,
typename Sentinel2>
struct cp_iters_sntls_ret<T, CPIter1, Sentinel1, CPIter2, Sentinel2, true>
{
using type = T;
};
template<
typename T,
typename CPIter1,
typename Sentinel1,
typename CPIter2,
typename Sentinel2>
using cp_iters_sntls_ret_t =
typename cp_iters_sntls_ret<T, CPIter1, Sentinel1, CPIter2, Sentinel2>::
type;
template<typename T, typename R1, typename R2>
using cp_rngs_alg_ret_t = cp_iters_sntls_ret_t<
T,
iterator_t<R1>,
sentinel_t<R1>,
iterator_t<R2>,
sentinel_t<R2>>;
template<int Size, typename T>
constexpr bool is_cu_iter_v =
Size == 1 ? is_char_iter_v<T> : is_16_iter_v<T>;
template<
int Size,
typename T,
typename U,
bool UIsCUIter = is_cu_iter_v<Size, U>>
struct cu_iter_ret
{
};
template<int Size, typename T, typename U>
struct cu_iter_ret<Size, T, U, true>
{
using type = T;
};
template<int Size, typename T, typename U>
using cu_iter_ret_t = typename cu_iter_ret<Size, T, U>::type;
template<int Size, typename T>
constexpr bool is_cu_range_v =
Size == 1 ? is_char_range_v<T> : is_char16_range_v<T>;
template<
int Size,
typename T,
typename U,
typename Exclude,
bool UIsCURange =
is_cu_range_v<Size, U> && !std::is_same<U, Exclude>::value>
struct cu_rng_alg_ret
{
};
template<int Size, typename T, typename U, typename Exclude>
struct cu_rng_alg_ret<Size, T, U, Exclude, true>
{
using type = T;
};
template<int Size, typename T, typename U, typename Exclude = void>
using cu_rng_alg_ret_t = typename cu_rng_alg_ret<Size, T, U, Exclude>::type;
template<typename T>
using is_grapheme_iter_expr = std::integral_constant<
bool,
is_cp_iter_v<
remove_cv_ref_t<decltype(std::declval<const T>().base())>>>;
template<typename T>
using is_grapheme_iter =
detected_or_t<std::false_type, is_grapheme_iter_expr, T>;
template<
typename T,
typename Iter,
bool R1IsGraphemeIter = is_grapheme_iter<Iter>::value>
struct graph_iter_alg_ret
{};
template<typename T, typename Iter>
struct graph_iter_alg_ret<T, Iter, true>
{
using type = T;
};
template<typename T, typename Iter>
using graph_iter_alg_ret_t = typename graph_iter_alg_ret<T, Iter>::type;
template<
typename T,
typename Iter1,
typename Iter2,
bool Iter1Iter2AreGraphemeIter =
is_grapheme_iter<Iter1>::value && is_grapheme_iter<Iter2>::value>
struct graph_iters_alg_ret
{};
template<typename T, typename Iter1, typename Iter2>
struct graph_iters_alg_ret<T, Iter1, Iter2, true>
{
using type = T;
};
template<typename T, typename Iter1, typename Iter2>
using graph_iters_alg_ret_t =
typename graph_iters_alg_ret<T, Iter1, Iter2>::type;
template<typename Size, typename T>
using is_grapheme_cu_iter_expr = std::integral_constant<
bool,
is_cp_iter_v<
remove_cv_ref_t<decltype(std::declval<const T>().base())>> &&
is_cu_iter_v<
Size::value,
remove_cv_ref_t<
decltype(std::declval<const T>().base().base())>>>;
template<int Size, typename T>
using is_grapheme_cu_iter = detected_or_t<
std::false_type,
is_grapheme_cu_iter_expr,
std::integral_constant<int, Size>,
T>;
template<
int Size,
typename T,
typename R1,
bool R1IsGraphemeIter = is_grapheme_cu_iter<Size, R1>::value>
struct graph_iter_cu_alg_ret
{};
template<int Size, typename T, typename R1>
struct graph_iter_cu_alg_ret<Size, T, R1, true>
{
using type = T;
};
template<int Size, typename T, typename R1>
using graph_iter_alg_cu_ret_t =
typename graph_iter_cu_alg_ret<Size, T, R1>::type;
template<typename T>
using is_grapheme_range_expr = std::integral_constant<
bool,
is_cp_iter_v<remove_cv_ref_t<
decltype(std::declval<const T>().begin().base())>> &&
is_cp_iter_v<remove_cv_ref_t<
decltype(std::declval<const T>().end().base())>> &&
void_<
decltype(std::declval<const T>().begin().base().base()),
decltype(std::declval<const T>().end().base().base())>::value>;
template<typename T>
using is_grapheme_range =
detected_or_t<std::false_type, is_grapheme_range_expr, T>;
template<
typename T,
typename R1,
bool R1IsGraphemeRange = is_grapheme_range<R1>::value>
struct graph_rng_alg_ret
{};
template<typename T, typename R1>
struct graph_rng_alg_ret<T, R1, true>
{
using type = T;
};
template<typename T, typename R1>
using graph_rng_alg_ret_t = typename graph_rng_alg_ret<T, R1>::type;
template<typename T>
using is_cp_grapheme_range_expr = std::integral_constant<
bool,
is_cp_iter_v<remove_cv_ref_t<
decltype(std::declval<const T>().begin().base())>> &&
is_cp_iter_v<remove_cv_ref_t<
decltype(std::declval<const T>().end().base())>>>;
template<typename T>
using is_cp_grapheme_range =
detected_or_t<std::false_type, is_cp_grapheme_range_expr, T>;
template<
typename T,
typename R1,
bool R1IsGraphemeRange = is_grapheme_range<R1>::value>
struct cp_graph_rng_alg_ret
{};
template<typename T, typename R1>
struct cp_graph_rng_alg_ret<T, R1, true>
{
using type = T;
};
template<typename T, typename R1>
using cp_graph_rng_alg_ret_t = typename cp_graph_rng_alg_ret<T, R1>::type;
template<
typename T,
typename R1,
typename R2,
bool R1R2AreGraphemeRanges =
is_cp_grapheme_range<R1>::value && is_cp_grapheme_range<R2>::value>
struct graph_rngs_alg_ret
{};
template<typename T, typename R1, typename R2>
struct graph_rngs_alg_ret<T, R1, R2, true>
{
using type = T;
};
template<typename T, typename R1, typename R2>
using graph_rngs_alg_ret_t = typename graph_rngs_alg_ret<T, R1, R2>::type;
template<
typename T,
typename R1,
typename R2,
bool R1IsGraphemeRangeButNotR2 =
is_cp_grapheme_range<R1>::value && !is_cp_grapheme_range<R2>::value>
struct lazy_graph_rng_and_non_alg_ret
{};
template<typename T, typename R1, typename R2>
struct lazy_graph_rng_and_non_alg_ret<T, R1, R2, true>
{
using type = typename T::type;
};
template<typename T, typename R1, typename R2>
using lazy_graph_rng_and_non_alg_ret_t =
typename lazy_graph_rng_and_non_alg_ret<T, R1, R2>::type;
template<
typename T,
typename R1,
typename R2,
bool R1IsGraphemeRangeButNotR2 =
is_cp_grapheme_range<R1>::value && !is_cp_grapheme_range<R2>::value>
struct graph_rng_and_non_alg_ret
{};
template<typename T, typename R1, typename R2>
struct graph_rng_and_non_alg_ret<T, R1, R2, true>
{
using type = T;
};
template<typename T, typename R1, typename R2>
using graph_rng_and_non_alg_ret_t =
typename graph_rng_and_non_alg_ret<T, R1, R2>::type;
template<
typename T,
typename R1,
typename R2,
bool R1R2AreNotGraphemeRanges = !is_cp_grapheme_range<R1>::value &&
!is_cp_grapheme_range<R2>::value>
struct non_graph_rngs_alg_ret
{};
template<typename T, typename R1, typename R2>
struct non_graph_rngs_alg_ret<T, R1, R2, true>
{
using type = T;
};
template<typename T, typename R1, typename R2>
using non_graph_rngs_alg_ret_t =
typename non_graph_rngs_alg_ret<T, R1, R2>::type;
template<
typename T,
typename R1,
typename R2,
bool R1R2AreNotGraphemeRanges = !is_cp_grapheme_range<R1>::value &&
!is_cp_grapheme_range<R2>::value>
struct lazy_non_graph_rngs_alg_ret
{};
template<typename T, typename R1, typename R2>
struct lazy_non_graph_rngs_alg_ret<T, R1, R2, true>
{
using type = typename T::type;
};
template<typename T, typename R1, typename R2>
using lazy_non_graph_rngs_alg_ret_t =
typename lazy_non_graph_rngs_alg_ret<T, R1, R2>::type;
template<typename T>
using is_contig_grapheme_range_expr = std::integral_constant<
bool,
(std::is_same<
decltype(std::declval<const T>().begin().base().base()),
char const *>::value ||
std::is_same<
decltype(std::declval<const T>().begin().base().base()),
char *>::value) &&
(std::is_same<
decltype(std::declval<const T>().end().base().base()),
char const *>::value ||
std::is_same<
decltype(std::declval<const T>().end().base().base()),
char *>::value)>;
template<typename T>
using is_contig_grapheme_range =
detected_or_t<std::false_type, is_contig_grapheme_range_expr, T>;
template<
typename T,
typename R1,
bool R1IsContigGraphemeRange = is_contig_grapheme_range<R1>::value>
struct contig_graph_rng_alg_ret
{
};
template<typename T, typename R1>
struct contig_graph_rng_alg_ret<T, R1, true>
{
using type = T;
};
template<typename T, typename R1>
using contig_graph_rng_alg_ret_t =
typename contig_graph_rng_alg_ret<T, R1>::type;
inline std::size_t hash_combine_(std::size_t seed, std::size_t value)
{
return seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
template<int N>
struct hash_4_more_chars
{
template<typename Iter>
static std::size_t call(std::size_t curr, Iter it)
{
return curr;
}
};
template<>
struct hash_4_more_chars<8>
{
template<typename Iter>
static std::size_t call(std::size_t curr, Iter it)
{
curr <<= 32;
curr += (*(it + 4) << 24) + (*(it + 5) << 16) + (*(it + 2) << 6) +
(*(it + 7) << 0);
return curr;
}
};
template<typename CharRange>
std::size_t hash_char_range(CharRange const & r)
{
auto first = r.begin();
auto last = r.end();
auto const size = last - first;
auto const remainder = size % sizeof(std::size_t);
last -= remainder;
std::size_t retval = size;
for (; first != last; first += sizeof(std::size_t)) {
std::size_t curr = (*(first + 0) << 24) + (*(first + 1) << 16) +
(*(first + 2) << 8) + (*(first + 3) << 0);
curr = hash_4_more_chars<sizeof(std::size_t)>::call(curr, first);
retval = detail::hash_combine_(retval, curr);
}
first = last;
last += remainder;
for (; first != last; ++first) {
retval = detail::hash_combine_(retval, *first);
}
return retval;
}
template<typename GraphemeRange>
std::size_t hash_grapheme_range(GraphemeRange const & r)
{
std::size_t cps = 0;
std::size_t retval = std::accumulate(
r.begin().base(),
r.end().base(),
std::size_t(0),
[&cps](std::size_t seed, std::size_t value) {
++cps;
return detail::hash_combine_(seed, value);
});
return detail::hash_combine_(retval, cps);
}
template<typename Iter>
using char_value_expr = std::integral_constant<
bool,
std::is_integral<
typename std::iterator_traits<Iter>::value_type>::value &&
sizeof(typename std::iterator_traits<Iter>::value_type) == 1>;
template<typename Iter>
constexpr bool is_char_ptr_v = std::is_pointer<Iter>::value &&
detected_or_t<std::false_type, char_value_expr, Iter>::value;
template<typename Iter>
using _16_value_expr = std::integral_constant<
bool,
std::is_integral<
typename std::iterator_traits<Iter>::value_type>::value &&
sizeof(typename std::iterator_traits<Iter>::value_type) == 2>;
template<typename Iter>
constexpr bool is_16_ptr_v = std::is_pointer<Iter>::value &&
detected_or_t<std::false_type, _16_value_expr, Iter>::value;
template<typename Iter>
using cp_value_expr = std::integral_constant<
bool,
std::is_integral<
typename std::iterator_traits<Iter>::value_type>::value &&
sizeof(typename std::iterator_traits<Iter>::value_type) == 4>;
template<typename Iter>
constexpr bool is_cp_ptr_v = std::is_pointer<Iter>::value &&
detected_or_t<std::false_type, cp_value_expr, Iter>::value;
}}}
#endif

View File

@@ -1,154 +0,0 @@
// Copyright (C) 2022 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_BEGIN_END_HPP
#define BOOST_PARSER_DETAIL_TEXT_BEGIN_END_HPP
#include <boost/parser/detail/detection.hpp>
#include <initializer_list>
namespace boost::parser::detail { namespace text { namespace detail {
template<typename T>
T decay_copy(T) noexcept;
template<typename T>
struct static_const
{
static constexpr T value{};
};
template<typename T>
constexpr T static_const<T>::value;
namespace begin_impl {
template<typename T>
void begin(T &&) = delete;
template<typename T>
void begin(std::initializer_list<T>) = delete;
template<typename T>
using member_begin_expr = decltype(std::declval<T &>().begin());
template<typename T>
using adl_begin_expr = decltype(begin(std::declval<T &>()));
template<typename T>
constexpr bool has_member_begin_v = is_detected_v<member_begin_expr, T>;
template<typename T>
constexpr bool has_adl_begin_v = is_detected_v<adl_begin_expr, T>;
template<typename R>
using member_return_t =
decltype(detail::decay_copy(std::declval<R &>().begin()));
template<typename R>
using adl_return_t =
decltype(detail::decay_copy(begin(std::declval<R &>)));
struct impl
{
template<typename R, std::size_t N>
void operator()(R (&&)[N]) const = delete;
template<typename R, std::size_t N>
constexpr R * operator()(R (&array)[N]) const
{
return array;
}
template<typename R>
constexpr std::
enable_if_t<has_member_begin_v<R>, member_return_t<R>>
operator()(R && r) const
{
return r.begin();
}
template<typename R>
constexpr std::enable_if_t<
!has_member_begin_v<R> && has_adl_begin_v<R>,
adl_return_t<R>>
operator()(R && r) const
{
return begin(r);
}
};
}
#if 201703L <= __cplusplus
namespace _ {
inline constexpr begin_impl::impl begin;
}
using namespace _;
#else
namespace {
constexpr auto & begin = static_const<begin_impl::impl>::value;
}
#endif
namespace end_impl {
template<typename T>
void end(T &&) = delete;
template<typename T>
void end(std::initializer_list<T>) = delete;
template<typename T>
using member_end_expr = decltype(std::declval<T &>().end());
template<typename T>
using adl_end_expr = decltype(end(std::declval<T &>()));
template<typename T>
constexpr bool has_member_end_v = is_detected_v<member_end_expr, T>;
template<typename T>
constexpr bool has_adl_end_v = is_detected_v<adl_end_expr, T>;
template<typename R>
using member_return_t =
decltype(detail::decay_copy(std::declval<R &>().end()));
template<typename R>
using adl_return_t =
decltype(detail::decay_copy(end(std::declval<R &>)));
struct impl
{
template<typename R, std::size_t N>
void operator()(R (&&)[N]) const = delete;
template<typename R, std::size_t N>
constexpr R * operator()(R (&array)[N]) const
{
return array + N;
}
template<typename R>
constexpr std::enable_if_t<has_member_end_v<R>, member_return_t<R>>
operator()(R && r) const
{
return r.end();
}
template<typename R>
constexpr std::enable_if_t<
!has_member_end_v<R> && has_adl_end_v<R>,
adl_return_t<R>>
operator()(R && r) const
{
return end(r);
}
};
}
#if 201703L <= __cplusplus
namespace _ {
inline constexpr end_impl::impl end;
}
using namespace _;
#else
namespace {
constexpr auto & end = static_const<end_impl::impl>::value;
}
#endif
}}}
#endif

View File

@@ -1,24 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_DETAIL_ITERATOR_HPP
#define BOOST_PARSER_DETAIL_TEXT_DETAIL_ITERATOR_HPP
#include <boost/parser/detail/text/config.hpp>
#include <boost/parser/detail/stl_interfaces/reverse_iterator.hpp>
#include <iterator>
namespace boost::parser::detail { namespace text { namespace detail {
using reverse_char_iterator =
parser::detail::stl_interfaces::reverse_iterator<char *>;
using const_reverse_char_iterator =
parser::detail::stl_interfaces::reverse_iterator<char const *>;
}}}
#endif

View File

@@ -1,19 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_DETAIL_SENTINEL_TAG_HPP
#define BOOST_PARSER_DETAIL_TEXT_DETAIL_SENTINEL_TAG_HPP
#include <boost/parser/detail/text/config.hpp>
namespace boost::parser::detail { namespace text { namespace detail {
struct sentinel_tag
{};
struct non_sentinel_tag
{};
}}}
#endif

View File

@@ -1,47 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_IN_OUT_RESULT_HPP
#define BOOST_PARSER_DETAIL_TEXT_IN_OUT_RESULT_HPP
#include <boost/parser/detail/text/config.hpp>
namespace boost::parser::detail { namespace text {
/** A replacement for C++20's `std::ranges::in_out_result` for use in
pre-C++20 build modes. */
template<typename I, typename O>
struct in_out_result
{
[[no_unique_address]] I in;
[[no_unique_address]] O out;
};
}}
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
#include <ranges>
namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V2 {
namespace dtl {
template<typename R>
std::ranges::borrowed_iterator_t<R> result_iterator(R &&);
template<typename Ptr>
requires std::is_pointer_v<std::remove_reference_t<Ptr>>
Ptr result_iterator(Ptr &&);
template<typename T>
using uc_result_iterator =
decltype(dtl::result_iterator(std::declval<T>()));
}
}}}
#endif
#endif

View File

@@ -1,800 +0,0 @@
// Copyright (C) 2018 Robert N. Steagall
// Copyright (C) 2019 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_TRANSCODE_ALGORITHM_HPP
#define BOOST_PARSER_DETAIL_TEXT_TRANSCODE_ALGORITHM_HPP
#include <boost/parser/detail/text/in_out_result.hpp>
#include <boost/parser/detail/text/transcode_iterator.hpp>
#include <boost/parser/detail/text/unpack.hpp>
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
#include <algorithm>
#endif
#include <boost/parser/config.hpp>
namespace boost::parser::detail { namespace text {
template<typename Range>
struct utf_range_like_iterator
{
using type = decltype(std::declval<Range>().begin());
};
template<typename T>
struct utf_range_like_iterator<T *>
{
using type = T *;
};
template<std::size_t N, typename T>
struct utf_range_like_iterator<T[N]>
{
using type = T *;
};
template<std::size_t N, typename T>
struct utf_range_like_iterator<T (&)[N]>
{
using type = T *;
};
template<typename Range>
using utf_range_like_iterator_t =
typename utf_range_like_iterator<Range>::type;
/** An alias for `in_out_result` returned by algorithms that perform a
transcoding copy. */
template<typename Iter, typename OutIter>
using transcode_result = in_out_result<Iter, OutIter>;
namespace detail {
template<typename OutIter>
constexpr OutIter read_into_utf8_iter(uint32_t cp, OutIter out)
{
if (cp < 0x80) {
*out = static_cast<char>(cp);
++out;
} else if (cp < 0x800) {
*out = static_cast<char>(0xC0 + (cp >> 6));
++out;
*out = static_cast<char>(0x80 + (cp & 0x3f));
++out;
} else if (cp < 0x10000) {
*out = static_cast<char>(0xe0 + (cp >> 12));
++out;
*out = static_cast<char>(0x80 + ((cp >> 6) & 0x3f));
++out;
*out = static_cast<char>(0x80 + (cp & 0x3f));
++out;
} else {
*out = static_cast<char>(0xf0 + (cp >> 18));
++out;
*out = static_cast<char>(0x80 + ((cp >> 12) & 0x3f));
++out;
*out = static_cast<char>(0x80 + ((cp >> 6) & 0x3f));
++out;
*out = static_cast<char>(0x80 + (cp & 0x3f));
++out;
}
return out;
}
template<typename OutIter>
constexpr OutIter read_into_utf16_iter(uint32_t cp, OutIter out)
{
uint16_t const high_surrogate_base = 0xd7c0;
uint16_t const low_surrogate_base = 0xdc00;
if (cp < 0x10000) {
*out = static_cast<uint16_t>(cp);
++out;
} else {
*out = static_cast<uint16_t>(cp >> 10) + high_surrogate_base;
++out;
*out = static_cast<uint16_t>(cp & 0x3ff) + low_surrogate_base;
++out;
}
return out;
}
template<
bool UseN,
typename InputIter,
typename Sentinel,
typename OutIter>
transcode_result<InputIter, OutIter> transcode_utf_8_to_16(
InputIter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out,
std::input_iterator_tag)
{
for (; first != last && (!UseN || n); --n) {
unsigned char const c = *first;
if (c < 0x80) {
*out = *first;
++first;
++out;
} else {
auto const cp = detail::advance(first, last);
out = detail::read_into_utf16_iter(cp, out);
}
}
return {first, out};
}
template<bool UseN, typename Iter, typename OutIter>
transcode_result<Iter, OutIter> transcode_utf_8_to_16(
Iter first,
Iter last,
std::ptrdiff_t n,
OutIter out,
std::random_access_iterator_tag)
{
return transcode_utf_8_to_16<UseN>(
first, last, n, out, std::input_iterator_tag{});
}
template<
bool UseN,
typename InputIter,
typename Sentinel,
typename OutIter>
transcode_result<InputIter, OutIter> transcode_utf_8_to_32(
InputIter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out,
std::input_iterator_tag)
{
for (; first != last && (!UseN || n); --n) {
unsigned char const c = *first;
if (c < 0x80) {
*out = *first;
++first;
++out;
} else {
*out = detail::advance(first, last);
++out;
}
}
return {first, out};
}
template<bool UseN, typename Iter, typename OutIter>
transcode_result<Iter, OutIter> transcode_utf_8_to_32(
Iter first,
Iter last,
std::ptrdiff_t n,
OutIter out,
std::random_access_iterator_tag)
{
return transcode_utf_8_to_32<UseN>(
first, last, n, out, std::input_iterator_tag{});
}
template<format Tag>
struct tag_t
{};
template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_8(
tag_t<format::utf8>,
Iter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out)
{
for (; first != last && (!UseN || n); ++first, ++out) {
*out = *first;
--n;
}
return {first, out};
}
template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_16(
tag_t<format::utf8>,
Iter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out)
{
return detail::transcode_utf_8_to_16<UseN>(
first,
last,
n,
out,
typename std::iterator_traits<Iter>::iterator_category{});
}
template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_32(
tag_t<format::utf8>,
Iter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out)
{
return detail::transcode_utf_8_to_32<UseN>(
first,
last,
n,
out,
typename std::iterator_traits<Iter>::iterator_category{});
}
template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_8(
tag_t<format::utf16>,
Iter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out)
{
uint32_t const high_surrogate_max = 0xdbff;
uint16_t const high_surrogate_base = 0xd7c0;
uint16_t const low_surrogate_base = 0xdc00;
for (; first != last && (!UseN || n); ++first, --n) {
uint32_t const hi = *first;
if (surrogate(hi)) {
if (hi <= high_surrogate_max) {
++first;
if (first == last) {
uint32_t const cp = replacement_character;
out = detail::read_into_utf8_iter(cp, out);
++out;
return {first, out};
}
uint32_t const lo = *first;
if (low_surrogate(lo)) {
uint32_t const cp =
((hi - high_surrogate_base) << 10) +
(lo - low_surrogate_base);
out = detail::read_into_utf8_iter(cp, out);
continue;
}
}
out = detail::read_into_utf8_iter(
replacement_character, out);
} else {
out = detail::read_into_utf8_iter(hi, out);
}
}
return {first, out};
}
template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_16(
tag_t<format::utf16>,
Iter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out)
{
for (; first != last && (!UseN || n); ++first, ++out, --n) {
*out = *first;
}
return {first, out};
}
template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_32(
tag_t<format::utf16>,
Iter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out)
{
uint32_t const high_surrogate_max = 0xdbff;
uint16_t const high_surrogate_base = 0xd7c0;
uint16_t const low_surrogate_base = 0xdc00;
for (; first != last && (!UseN || n); ++first, --n) {
uint32_t const hi = *first;
if (surrogate(hi)) {
if (hi <= high_surrogate_max) {
++first;
if (first == last) {
*out = replacement_character;
++out;
return {first, out};
}
uint32_t const lo = *first;
if (low_surrogate(lo)) {
uint32_t const cp =
((hi - high_surrogate_base) << 10) +
(lo - low_surrogate_base);
*out = cp;
++out;
continue;
}
}
*out = replacement_character;
++out;
} else {
*out = hi;
++out;
}
}
return {first, out};
}
template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_8(
tag_t<format::utf32>,
Iter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out)
{
for (; first != last && (!UseN || n); ++first, --n) {
out = detail::read_into_utf8_iter(*first, out);
}
return {first, out};
}
template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_16(
tag_t<format::utf32>,
Iter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out)
{
for (; first != last && (!UseN || n); ++first, --n) {
out = detail::read_into_utf16_iter(*first, out);
}
return {first, out};
}
template<bool UseN, typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_32(
tag_t<format::utf32>,
Iter first,
Sentinel last,
std::ptrdiff_t n,
OutIter out)
{
for (; first != last && (!UseN || n); ++first, ++out, --n) {
*out = *first;
}
return {first, out};
}
}
#if 0
/** Copies the code points in the range [first, last) to out, changing the
encoding from UTF-8 to UTF-32. */
template<typename InputIter, typename Sentinel, typename OutIter>
transcode_result<InputIter, OutIter> transcode_utf_8_to_32_take_n(
InputIter first, Sentinel last, std::ptrdiff_t n, OutIter out)
{
auto const r = detail::unpack_iterator_and_sentinel(first, last);
return detail::transcode_to_32<true>(
detail::tag_t<r.format_tag>{}, r.first, r.last, n, out);
}
/** Copies the first `n` code points in the range [first, last) to out,
changing the encoding from UTF-8 to UTF-32. */
template<typename InputIter, typename Sentinel, typename OutIter>
transcode_result<InputIter, OutIter> transcode_utf_8_to_32_take_n(
InputIter first, Sentinel last, std::ptrdiff_t n, OutIter out)
{
auto const r = detail::unpack_iterator_and_sentinel(first, last);
return detail::transcode_to_32<true>(
detail::tag_t<r.format_tag>{}, r.first, r.last, n, out);
}
/** Copies the first `n` code points in the range [first, last) to out,
changing the encoding from UTF-8 to UTF-32. */
template<typename InputIter, typename Sentinel, typename OutIter>
transcode_result<InputIter, OutIter>
transcode_utf_8_to_32_take_n(Range && r, std::ptrdiff_t n, OutIter out)
{
return detail::transcode_utf_8_to_32_dispatch<true, Range, OutIter>::
call(r, n, out)
.out;
}
#endif
}}
namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V1 {
#if defined(BOOST_TEXT_DOXYGEN)
// -> utf8
/** Copies the code points in the range `[first, last)` to `out`, changing
the encoding to UTF-8. */
template<
std::input_iterator I,
std::sentinel_for<I> S,
std::output_iterator<uint8_t> O>
requires(
utf16_code_unit<std::iter_value_t<I>> ||
utf32_code_unit<std::iter_value_t<I>>)
transcode_result<I, O> transcode_to_utf8(I first, S last, O out);
/** Copies the code points in the range `[p, null_sentinel)` to `out`,
changing the encoding to UTF-8. */
template<typename Ptr, std::output_iterator<uint8_t> O>
requires(utf16_pointer<Ptr> || utf32_pointer<Ptr>)
transcode_result<Ptr, O> transcode_to_utf8(Ptr p, O out);
/** Copies the code points in the array `arr` to `out`, changing the
encoding to UTF-8. */
template<std::size_t N, typename Char, std::output_iterator<uint8_t> O>
requires (utf16_code_unit<Char> || utf32_code_unit<Char>)
transcode_result<Char *, O> transcode_to_utf8(Char (&arr)[N], O out);
/** Copies the code points in the range `r` to `out`, changing the
encoding to UTF-8. */
template<std::ranges::input_range R, std::output_iterator<uint8_t> O>
requires (utf16_code_unit<std::ranges::range_value_t<R>> ||
utf32_code_unit<std::ranges::range_value_t<R>>)
transcode_result<std::ranges::borrowed_iterator_t<R>, O>
transcode_to_utf8(R && r, O out);
// -> utf16
/** Copies the code points in the range `[first, last)` to `out`, changing
the encoding to UTF-16. */
template<
std::input_iterator I,
std::sentinel_for<I> S,
std::output_iterator<char16_t> O>
requires (utf8_code_unit<std::iter_value_t<I>> ||
utf32_code_unit<std::iter_value_t<I>>)
transcode_result<I, O> transcode_to_utf16(I first, S last, O out);
/** Copies the code points in the range `[p, null_sentinel)` to `out`,
changing the encoding to UTF-16. */
template<typename Ptr, std::output_iterator<char16_t> O>
requires (utf8_pointer<Ptr> || utf32_pointer<Ptr>)
transcode_result<Ptr, O> transcode_to_utf16(Ptr p, O out);
/** Copies the code points in the array `arr` to `out`, changing the
encoding to UTF-16. */
template<std::size_t N, typename Char, std::output_iterator<char16_t> O>
requires (utf8_code_unit<Char> || utf32_code_unit<Char>)
transcode_result<Char *, O> transcode_to_utf16(Char (&arr)[N], O out);
/** Copies the code points in the range `r` to `out`, changing the
encoding to UTF-16. */
template<std::ranges::input_range R, std::output_iterator<cjar16_t> O>
requires (utf8_code_unit<std::ranges::range_value_t<R>> ||
utf32_code_unit<std::ranges::range_value_t<R>>)
transcode_result<std::ranges::borrowed_iterator_t<R>, O>
transcode_to_utf16(R && r, O out);
// -> utf32
/** Copies the code points in the range `[first, last)` to `out`, changing
the encoding to UTF-32. */
template<
std::input_iterator I,
std::sentinel_for<I> S,
std::output_iterator<uint32_t> O>
requires (utf8_code_unit<std::iter_value_t<I>> ||
utf16_code_unit<std::iter_value_t<I>>)
transcode_result<I, O> transcode_to_utf32(I first, S last, O out);
/** Copies the code points in the range `[p, null_sentinel)` to `out`,
changing the encoding to UTF-32. */
template<typename Ptr, std::output_iterator<uint32_t> O>
requires (utf8_pointer<Ptr> || utf16_pointer<Ptr>)
transcode_result<Ptr, O> transcode_to_utf32(Ptr p, O out);
/** Copies the code points in the array `arr` to `out`, changing the
encoding to UTF-32. */
template<std::size_t N, typename Char, std::output_iterator<uint32_t> O>
requires (utf8_code_unit<Char> || utf16_code_unit<Char>)
transcode_result<Char *, O> transcode_to_utf32(Char (&arr)[N], O out);
/** Copies the code points in the range `r` to `out`, changing the
encoding to UTF-32. */
template<std::ranges::input_range R, std::output_iterator<uint32_t> O>
requires (utf8_code_unit<std::ranges::range_value_t<R>> ||
utf16_code_unit<std::ranges::range_value_t<R>>)
transcode_result<std::ranges::borrowed_iterator_t<R>, O>
transcode_to_utf32(R && r, O out);
#endif
namespace dtl {
template<
bool UseN,
typename Range,
typename OutIter,
bool _16Ptr = detail::is_16_ptr_v<Range>,
bool CPPtr = detail::is_cp_ptr_v<Range>>
struct transcode_to_8_dispatch
{
static constexpr auto
call(Range && r, std::ptrdiff_t n, OutIter out)
-> transcode_result<decltype(detail::begin(r)), OutIter>
{
auto const u = text::unpack_iterator_and_sentinel(
detail::begin(r), detail::end(r));
auto unpacked = detail::transcode_to_8<UseN>(
detail::tag_t<u.format_tag>{}, u.first, u.last, n, out);
return {u.repack(unpacked.in), unpacked.out};
}
};
template<bool UseN, typename Ptr, typename OutIter>
struct transcode_to_8_dispatch<UseN, Ptr, OutIter, true, false>
{
static constexpr auto
call(Ptr p, std::ptrdiff_t n, OutIter out)
{
return detail::transcode_to_8<UseN>(
detail::tag_t<format::utf16>{}, p, null_sentinel, n, out);
}
};
template<bool UseN, typename Ptr, typename OutIter>
struct transcode_to_8_dispatch<UseN, Ptr, OutIter, false, true>
{
static constexpr auto
call(Ptr p, std::ptrdiff_t n, OutIter out)
{
return detail::transcode_to_8<UseN>(
detail::tag_t<format::utf32>{}, p, null_sentinel, n, out);
}
};
template<
bool UseN,
typename Range,
typename OutIter,
bool CharPtr = detail::is_char_ptr_v<Range>,
bool CPPtr = detail::is_cp_ptr_v<Range>>
struct transcode_to_16_dispatch
{
static constexpr auto
call(Range && r, std::ptrdiff_t n, OutIter out)
-> transcode_result<decltype(detail::begin(r)), OutIter>
{
auto const u = text::unpack_iterator_and_sentinel(
detail::begin(r), detail::end(r));
auto unpacked = detail::transcode_to_16<UseN>(
detail::tag_t<u.format_tag>{}, u.first, u.last, n, out);
return {u.repack(unpacked.in), unpacked.out};
}
};
template<bool UseN, typename Ptr, typename OutIter>
struct transcode_to_16_dispatch<UseN, Ptr, OutIter, true, false>
{
static constexpr auto
call(Ptr p, std::ptrdiff_t n, OutIter out)
{
return detail::transcode_to_16<UseN>(
detail::tag_t<format::utf8>{}, p, null_sentinel, n, out);
}
};
template<bool UseN, typename Ptr, typename OutIter>
struct transcode_to_16_dispatch<UseN, Ptr, OutIter, false, true>
{
static constexpr auto
call(Ptr p, std::ptrdiff_t n, OutIter out)
{
return detail::transcode_to_16<UseN>(
detail::tag_t<format::utf32>{}, p, null_sentinel, n, out);
}
};
template<
bool UseN,
typename Range,
typename OutIter,
bool CharPtr = detail::is_char_ptr_v<Range>,
bool _16Ptr = detail::is_16_ptr_v<Range>>
struct transcode_to_32_dispatch
{
static constexpr auto
call(Range && r, std::ptrdiff_t n, OutIter out)
-> transcode_result<decltype(detail::begin(r)), OutIter>
{
auto const u = text::unpack_iterator_and_sentinel(
detail::begin(r), detail::end(r));
auto unpacked = detail::transcode_to_32<UseN>(
detail::tag_t<u.format_tag>{}, u.first, u.last, n, out);
return {u.repack(unpacked.in), unpacked.out};
}
};
template<bool UseN, typename Ptr, typename OutIter>
struct transcode_to_32_dispatch<UseN, Ptr, OutIter, true, false>
{
static constexpr auto
call(Ptr p, std::ptrdiff_t n, OutIter out)
{
return detail::transcode_to_32<UseN>(
detail::tag_t<format::utf8>{}, p, null_sentinel, n, out);
}
};
template<bool UseN, typename Ptr, typename OutIter>
struct transcode_to_32_dispatch<UseN, Ptr, OutIter, false, true>
{
static constexpr auto
call(Ptr p, std::ptrdiff_t n, OutIter out)
{
return detail::transcode_to_32<UseN>(
detail::tag_t<format::utf16>{}, p, null_sentinel, n, out);
}
};
}
template<typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_utf8(
Iter first, Sentinel last, OutIter out)
{
auto const r = text::unpack_iterator_and_sentinel(first, last);
auto unpacked = detail::transcode_to_8<false>(
detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
return {r.repack(unpacked.in), unpacked.out};
}
template<typename Range, typename OutIter>
transcode_result<utf_range_like_iterator_t<Range>, OutIter>
transcode_to_utf8(Range && r, OutIter out)
{
return dtl::transcode_to_8_dispatch<false, Range, OutIter>::call(
r, -1, out);
}
template<typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_utf16(
Iter first, Sentinel last, OutIter out)
{
auto const r = text::unpack_iterator_and_sentinel(first, last);
auto unpacked = detail::transcode_to_16<false>(
detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
return {r.repack(unpacked.in), unpacked.out};
}
template<typename Range, typename OutIter>
transcode_result<utf_range_like_iterator_t<Range>, OutIter>
transcode_to_utf16(Range && r, OutIter out)
{
return dtl::transcode_to_16_dispatch<false, Range, OutIter>::call(
r, -1, out);
}
template<typename Iter, typename Sentinel, typename OutIter>
transcode_result<Iter, OutIter> transcode_to_utf32(
Iter first, Sentinel last, OutIter out)
{
auto const r = text::unpack_iterator_and_sentinel(first, last);
auto unpacked = detail::transcode_to_32<false>(
detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
return {r.repack(unpacked.in), unpacked.out};
}
template<typename Range, typename OutIter>
transcode_result<utf_range_like_iterator_t<Range>, OutIter>
transcode_to_utf32(Range && r, OutIter out)
{
return dtl::transcode_to_32_dispatch<false, Range, OutIter>::call(
r, -1, out);
}
}}}
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
namespace boost::parser::detail { namespace text { BOOST_PARSER_DETAIL_TEXT_NAMESPACE_V2 {
// -> utf8
template<
std::input_iterator I,
std::sentinel_for<I> S,
std::output_iterator<uint8_t> O>
requires(
utf16_code_unit<std::iter_value_t<I>> ||
utf32_code_unit<std::iter_value_t<I>>)
transcode_result<I, O> transcode_to_utf8(I first, S last, O out)
{
auto const r = text::unpack_iterator_and_sentinel(first, last);
auto unpacked = detail::transcode_to_8<false>(
detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
return {r.repack(unpacked.in), unpacked.out};
}
template<typename R, std::output_iterator<uint32_t> O>
requires(utf16_range_like<R> || utf32_range_like<R>)
transcode_result<dtl::uc_result_iterator<R>, O> transcode_to_utf8(
R && r, O out)
{
if constexpr (std::is_pointer_v<std::remove_reference_t<R>>) {
return text::transcode_to_utf8(r, null_sentinel, out);
} else {
return text::transcode_to_utf8(
std::ranges::begin(r), std::ranges::end(r), out);
}
}
// -> utf16
template<
std::input_iterator I,
std::sentinel_for<I> S,
std::output_iterator<char16_t> O>
requires(
utf8_code_unit<std::iter_value_t<I>> ||
utf32_code_unit<std::iter_value_t<I>>)
transcode_result<I, O> transcode_to_utf16(I first, S last, O out)
{
auto const r = text::unpack_iterator_and_sentinel(first, last);
auto unpacked = detail::transcode_to_16<false>(
detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
return {r.repack(unpacked.in), unpacked.out};
}
template<typename R, std::output_iterator<uint32_t> O>
requires(utf8_range_like<R> || utf32_range_like<R>)
transcode_result<dtl::uc_result_iterator<R>, O> transcode_to_utf16(
R && r, O out)
{
if constexpr (std::is_pointer_v<std::remove_reference_t<R>>) {
return text::transcode_to_utf16(r, null_sentinel, out);
} else {
return text::transcode_to_utf16(
std::ranges::begin(r), std::ranges::end(r), out);
}
}
// -> utf32
template<
std::input_iterator I,
std::sentinel_for<I> S,
std::output_iterator<uint32_t> O>
requires(
utf8_code_unit<std::iter_value_t<I>> ||
utf16_code_unit<std::iter_value_t<I>>)
transcode_result<I, O> transcode_to_utf32(I first, S last, O out)
{
auto const r = text::unpack_iterator_and_sentinel(first, last);
auto unpacked = detail::transcode_to_32<false>(
detail::tag_t<r.format_tag>{}, r.first, r.last, -1, out);
return {r.repack(unpacked.in), unpacked.out};
}
template<typename R, std::output_iterator<uint32_t> O>
requires(utf8_range_like<R> || utf16_range_like<R>)
transcode_result<dtl::uc_result_iterator<R>, O> transcode_to_utf32(
R && r, O out)
{
if constexpr (std::is_pointer_v<std::remove_reference_t<R>>) {
return text::transcode_to_utf32(r, null_sentinel, out);
} else {
return text::transcode_to_utf32(
std::ranges::begin(r), std::ranges::end(r), out);
}
}
}}}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,101 +0,0 @@
// Copyright (C) 2023 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_TRANSCODE_ITERATOR_FWD_HPP
#define BOOST_PARSER_DETAIL_TEXT_TRANSCODE_ITERATOR_FWD_HPP
#include <boost/parser/detail/text/concepts.hpp>
namespace boost::parser::detail { namespace text {
struct use_replacement_character;
namespace detail {
template<
typename RepackedIterator,
typename I,
typename S,
typename Then>
struct bidi_repacker;
}
}}
namespace boost::parser::detail { namespace text {
namespace detail {
template<format Format>
constexpr auto format_to_type();
template<format Format>
using format_to_type_t = decltype(format_to_type<Format>());
}
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<
format FromFormat,
format ToFormat,
std::input_iterator I,
std::sentinel_for<I> S = I,
transcoding_error_handler ErrorHandler = use_replacement_character>
requires std::convertible_to<std::iter_value_t<I>, detail::format_to_type_t<FromFormat>>
#else
template<
format FromFormat,
format ToFormat,
typename I,
typename S = I,
typename ErrorHandler = use_replacement_character>
#endif
class utf_iterator;
#if BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD
template<
utf8_iter I,
std::sentinel_for<I> S = I,
transcoding_error_handler ErrorHandler = use_replacement_character>
using utf_8_to_16_iterator =
utf_iterator<format::utf8, format::utf16, I, S, ErrorHandler>;
template<
utf16_iter I,
std::sentinel_for<I> S = I,
transcoding_error_handler ErrorHandler = use_replacement_character>
using utf_16_to_8_iterator =
utf_iterator<format::utf16, format::utf8, I, S, ErrorHandler>;
template<
utf8_iter I,
std::sentinel_for<I> S = I,
transcoding_error_handler ErrorHandler = use_replacement_character>
using utf_8_to_32_iterator =
utf_iterator<format::utf8, format::utf32, I, S, ErrorHandler>;
template<
utf32_iter I,
std::sentinel_for<I> S = I,
transcoding_error_handler ErrorHandler = use_replacement_character>
using utf_32_to_8_iterator =
utf_iterator<format::utf32, format::utf8, I, S, ErrorHandler>;
template<
utf16_iter I,
std::sentinel_for<I> S = I,
transcoding_error_handler ErrorHandler = use_replacement_character>
using utf_16_to_32_iterator =
utf_iterator<format::utf16, format::utf32, I, S, ErrorHandler>;
template<
utf32_iter I,
std::sentinel_for<I> S = I,
transcoding_error_handler ErrorHandler = use_replacement_character>
using utf_32_to_16_iterator =
utf_iterator<format::utf32, format::utf16, I, S, ErrorHandler>;
#endif
}}
#endif

View File

@@ -1,833 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_TRANSCODE_VIEW_HPP
#define BOOST_PARSER_DETAIL_TEXT_TRANSCODE_VIEW_HPP
#include <boost/parser/detail/text/transcode_algorithm.hpp>
#include <boost/parser/detail/text/transcode_iterator.hpp>
#include <boost/parser/detail/stl_interfaces/view_interface.hpp>
#include <boost/parser/detail/stl_interfaces/view_adaptor.hpp>
#include <climits>
namespace boost::parser::detail { namespace text {
namespace detail {
template<class I>
constexpr auto iterator_to_tag()
{
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
if constexpr (std::random_access_iterator<I>) {
return std::random_access_iterator_tag{};
} else if constexpr (std::bidirectional_iterator<I>) {
return std::bidirectional_iterator_tag{};
} else if constexpr (std::forward_iterator<I>) {
#else
if constexpr (detail::random_access_iterator_v<I>) {
return std::random_access_iterator_tag{};
} else if constexpr (detail::bidirectional_iterator_v<I>) {
return std::bidirectional_iterator_tag{};
} else if constexpr (detail::forward_iterator_v<I>) {
#endif
return std::forward_iterator_tag{};
} else {
return std::input_iterator_tag{};
}
}
template<class I>
using iterator_to_tag_t = decltype(iterator_to_tag<I>());
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class T>
using with_reference = T &;
template<typename T>
concept can_reference = requires { typename with_reference<T>; };
#endif
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class Char>
struct cast_to_charn {
constexpr Char operator()(Char c) const { return c; }
};
#else
struct cast_to_char8;
struct cast_to_char16;
struct cast_to_char32;
template<typename Tag, typename Arg>
auto function_for_tag(Arg arg)
{
#if defined(__cpp_char8_t)
if constexpr (std::is_same_v<Tag, cast_to_char8>) {
return (char8_t)arg;
} else
#endif
if constexpr (std::is_same_v<Tag, cast_to_char16>) {
return (char16_t)arg;
} else if constexpr (std::is_same_v<Tag, cast_to_char32>) {
return (char32_t)arg;
}
}
#endif
}
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<std::ranges::input_range V, auto F>
requires std::ranges::view<V> &&
std::regular_invocable<decltype(F)&, std::ranges::range_reference_t<V>> &&
detail::can_reference<std::invoke_result_t<decltype(F)&, std::ranges::range_reference_t<V>>>
#else
template<typename V, typename F> // F is a tag type in c++17
#endif
class project_view : public stl_interfaces::view_interface<project_view<V, F>>
{
V base_ = V();
template<bool Const>
class iterator;
template<bool Const>
class sentinel;
public:
constexpr project_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::default_initializable<V>
#endif
= default;
constexpr explicit project_view(V base) : base_(std::move(base)) {}
constexpr V& base() & { return base_; }
constexpr const V& base() const& { return base_; }
constexpr V base() && { return std::move(base_); }
constexpr iterator<false> begin() { return iterator<false>{detail::begin(base_)}; }
constexpr iterator<true> begin() const
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::ranges::range<const V>
#endif
{ return iterator<true>{detail::begin(base_)}; }
constexpr sentinel<false> end() { return sentinel<false>{detail::end(base_)}; }
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
constexpr iterator<false> end() requires std::ranges::common_range<V>
{ return iterator<false>{detail::end(base_)}; }
#endif
constexpr sentinel<true> end() const
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::ranges::range<const V>
{ return sentinel<true>{detail::end(base_)}; }
constexpr iterator<true> end() const
requires std::ranges::common_range<const V>
#endif
{ return iterator<true>{detail::end(base_)}; }
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
constexpr auto size() requires std::ranges::sized_range<V> { return std::ranges::size(base_); }
constexpr auto size() const requires std::ranges::sized_range<const V> { return std::ranges::size(base_); }
#endif
};
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<std::ranges::input_range V, auto F>
requires std::ranges::view<V> &&
std::regular_invocable<decltype(F)&, std::ranges::range_reference_t<V>> &&
detail::can_reference<std::invoke_result_t<decltype(F)&, std::ranges::range_reference_t<V>>>
#else
template<typename V, typename F>
#endif
template<bool Const>
class project_view<V, F>::iterator
: public boost::parser::detail::stl_interfaces::proxy_iterator_interface<
iterator<Const>,
detail::iterator_to_tag_t<detail::iterator_t<detail::maybe_const<Const, V>>>,
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
std::invoke_result_t<decltype(F)&, detail::range_reference_t<V>>
#else
decltype(detail::function_for_tag<F>(0))
#endif
>
{
using iterator_type = detail::iterator_t<detail::maybe_const<Const, V>>;
using sentinel_type = detail::sentinel_t<detail::maybe_const<Const, V>>;
using reference_type =
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
std::invoke_result_t<decltype(F) &, detail::range_reference_t<V>>
#else
decltype(detail::function_for_tag<F>(0))
#endif
;
using sentinel = project_view<V, F>::sentinel<Const>;
friend boost::parser::detail::stl_interfaces::access;
iterator_type & base_reference() noexcept { return it_; }
iterator_type base_reference() const { return it_; }
iterator_type it_ = iterator_type();
friend project_view<V, F>::sentinel<Const>;
template<bool OtherConst>
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
#endif
friend constexpr bool operator==(const iterator<OtherConst> & x,
const sentinel & y);
template<bool OtherConst>
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::sized_sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
#endif
friend constexpr detail::range_difference_t<detail::maybe_const<OtherConst, V>>
operator-(const iterator<OtherConst> & x, const sentinel & y);
template<bool OtherConst>
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::sized_sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
#endif
friend constexpr detail::range_difference_t<detail::maybe_const<OtherConst, V>>
operator-(const sentinel & y, const iterator<OtherConst> & x);
public:
constexpr iterator() = default;
constexpr iterator(iterator_type it) : it_(std::move(it)) {}
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
constexpr reference_type operator*() const { return F(*it_); }
#else
constexpr reference_type operator*() const
{
return detail::function_for_tag<F>(*it_);
}
#endif
};
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<std::ranges::input_range V, auto F>
requires std::ranges::view<V> &&
std::regular_invocable<decltype(F)&, std::ranges::range_reference_t<V>> &&
detail::can_reference<std::invoke_result_t<decltype(F)&, std::ranges::range_reference_t<V>>>
#else
template<typename V, typename F>
#endif
template<bool Const>
class project_view<V, F>::sentinel
{
using Base = detail::maybe_const<Const, V>;
using sentinel_type = detail::sentinel_t<Base>;
sentinel_type end_ = sentinel_type();
public:
constexpr sentinel() = default;
constexpr explicit sentinel(sentinel_type end) : end_(std::move(end)) {}
#if !BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<bool Enable = Const, class = std::enable_if_t<Enable>>
#endif
constexpr sentinel(sentinel<!Const> i)
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires Const &&
std::convertible_to<detail::sentinel_t<V>, detail::sentinel_t<Base>>
#endif
: end_(std::move(i.end_))
{}
constexpr sentinel_type base() const { return end_; }
template<bool OtherConst>
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
#endif
friend constexpr bool operator==(const iterator<OtherConst> & x,
const sentinel & y)
{ return x.it_ == y.end_; }
template<bool OtherConst>
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::sized_sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
#endif
friend constexpr detail::range_difference_t<detail::maybe_const<OtherConst, V>>
operator-(const iterator<OtherConst> & x, const sentinel & y)
{ return x.it_ - y.end_; }
template<bool OtherConst>
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::sized_sentinel_for<sentinel_type, std::ranges::iterator_t<detail::maybe_const<OtherConst, V>>>
#endif
friend constexpr detail::range_difference_t<detail::maybe_const<OtherConst, V>>
operator-(const sentinel & y, const iterator<OtherConst> & x)
{ return y.end_ - x.it_; }
};
#if BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD
template<class R, auto F>
project_view(R &&) -> project_view<std::views::all_t<R>, F>;
#endif
namespace detail {
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<auto F>
#else
template<typename F>
#endif
struct project_impl : stl_interfaces::range_adaptor_closure<project_impl<F>>
{
template<class R>
using project_view_type = project_view<R, F>;
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class R>
requires std::ranges::viewable_range<R> &&
std::ranges::input_range<R> &&
std::regular_invocable<decltype(F)&, std::ranges::range_reference_t<R>> &&
detail::can_reference<std::invoke_result_t<decltype(F)&, std::ranges::range_reference_t<R>>>
#else
template<class R>
#endif
[[nodiscard]] constexpr auto operator()(R && r) const
{
#if BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD
return project_view_type(std::forward<R>(r));
#else
return project_view_type<R>(std::forward<R>(r));
#endif
}
};
}
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<auto F>
#else
template<typename F>
#endif
constexpr detail::project_impl<F> project{};
#if BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD
template<class V>
using char8_view = project_view<V, detail::cast_to_charn<char8_t>{}>;
template<class V>
using char16_view = project_view<V, detail::cast_to_charn<char16_t>{}>;
template<class V>
using char32_view = project_view<V, detail::cast_to_charn<char32_t>{}>;
#else
#if defined(__cpp_char8_t)
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<std::ranges::input_range V>
requires std::ranges::view<V> && std::convertible_to<std::ranges::range_reference_t<V>, char8_t>
class char8_view : public project_view<V, detail::cast_to_charn<char8_type>{}>
#else
template<typename V>
class char8_view : public project_view<V, detail::cast_to_char8>
#endif
{
public:
constexpr char8_view() requires std::default_initializable<V> = default;
constexpr char8_view(V base) :
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
project_view<V, detail::cast_to_charn<char8_t>{}>{std::move(base)}
#else
project_view<V, detail::cast_to_char8>{std::move(base)}
#endif
{}
};
#endif
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<std::ranges::input_range V>
requires std::ranges::view<V> && std::convertible_to<std::ranges::range_reference_t<V>, char16_t>
class char16_view : public project_view<V, detail::cast_to_charn<char16_t>{}>
#else
template<typename V>
class char16_view : public project_view<V, detail::cast_to_char16>
#endif
{
public:
constexpr char16_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::default_initializable<V>
#endif
= default;
constexpr char16_view(V base) :
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
project_view<V, detail::cast_to_charn<char16_t>{}>{std::move(base)}
#else
project_view<V, detail::cast_to_char16>{std::move(base)}
#endif
{}
};
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<std::ranges::input_range V>
requires std::ranges::view<V> && std::convertible_to<std::ranges::range_reference_t<V>, char32_t>
class char32_view : public project_view<V, detail::cast_to_charn<char32_t>{}>
#else
template<typename V>
class char32_view : public project_view<V, detail::cast_to_char32>
#endif
{
public:
constexpr char32_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::default_initializable<V>
#endif
= default;
constexpr char32_view(V base) :
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
project_view<V, detail::cast_to_charn<char32_t>{}>{std::move(base)}
#else
project_view<V, detail::cast_to_char32>{std::move(base)}
#endif
{}
};
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class R>
char8_view(R &&) -> char8_view<std::views::all_t<R>>;
template<class R>
char16_view(R &&) -> char16_view<std::views::all_t<R>>;
template<class R>
char32_view(R &&) -> char32_view<std::views::all_t<R>>;
#endif
#endif
namespace detail {
template<template<class> class View, format Format>
struct as_charn_impl : stl_interfaces::range_adaptor_closure<as_charn_impl<View, Format>>
{
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class R>
requires (std::ranges::viewable_range<R> &&
std::ranges::input_range<R> &&
std::convertible_to<std::ranges::range_reference_t<R>, format_to_type_t<Format>>) ||
utf_pointer<std::remove_cvref_t<R>>
#else
template<class R>
#endif
[[nodiscard]] constexpr auto operator()(R && r) const
{
using T = remove_cv_ref_t<R>;
if constexpr (detail::is_empty_view<T>) {
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
return std::ranges::empty_view<format_to_type_t<Format>>{};
#else
return 42; // Never gonna happen.
#endif
} else if constexpr (std::is_pointer_v<T>) {
return View(
BOOST_PARSER_DETAIL_TEXT_SUBRANGE(r, null_sentinel));
} else {
return View(std::forward<R>(r));
}
}
};
template<class T>
constexpr bool is_charn_view = false;
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class V>
constexpr bool is_charn_view<char8_view<V>> = true;
#endif
template<class V>
constexpr bool is_charn_view<char16_view<V>> = true;
template<class V>
constexpr bool is_charn_view<char32_view<V>> = true;
}
#if defined(__cpp_char8_t)
inline constexpr detail::as_charn_impl<char8_view, format::utf8> as_char8_t;
#endif
inline constexpr detail::as_charn_impl<char16_view, format::utf16> as_char16_t;
inline constexpr detail::as_charn_impl<char32_view, format::utf32> as_char32_t;
// clang-format off
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<utf_range V>
requires std::ranges::view<V> && std::ranges::forward_range<V>
#else
template<typename V>
#endif
class unpacking_view : public stl_interfaces::view_interface<unpacking_view<V>> {
V base_ = V();
public:
constexpr unpacking_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::default_initializable<V>
#endif
= default;
constexpr unpacking_view(V base) : base_(std::move(base)) {}
constexpr V base() const &
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::copy_constructible<V>
#endif
{ return base_; }
constexpr V base() && { return std::move(base_); }
constexpr auto code_units() const noexcept {
auto unpacked = boost::parser::detail::text::unpack_iterator_and_sentinel(detail::begin(base_), detail::end(base_));
return BOOST_PARSER_DETAIL_TEXT_SUBRANGE(unpacked.first, unpacked.last);
}
constexpr auto begin() { return code_units().begin(); }
constexpr auto begin() const { return code_units().begin(); }
constexpr auto end() { return code_units().end(); }
constexpr auto end() const { return code_units().end(); }
};
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class R>
unpacking_view(R &&) -> unpacking_view<std::views::all_t<R>>;
#endif
// clang-format on
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<format Format, utf_range V>
requires std::ranges::view<V>
#else
template<format Format, typename V>
#endif
class utf_view : public stl_interfaces::view_interface<utf_view<Format, V>>
{
V base_ = V();
template<format FromFormat, class I, class S>
static constexpr auto make_begin(I first, S last)
{
if constexpr (detail::bidirectional_iterator_v<I>) {
return utf_iterator<FromFormat, Format, I, S>{first, first, last};
} else {
return utf_iterator<FromFormat, Format, I, S>{first, last};
}
}
template<format FromFormat, class I, class S>
static constexpr auto make_end(I first, S last)
{
if constexpr (!std::is_same_v<I, S>) {
return last;
} else if constexpr (detail::bidirectional_iterator_v<I>) {
return utf_iterator<FromFormat, Format, I, S>{first, last, last};
} else {
return utf_iterator<FromFormat, Format, I, S>{last, last};
}
}
public:
constexpr utf_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::default_initializable<V>
#endif
= default;
constexpr utf_view(V base) : base_{std::move(base)} {}
constexpr V base() const &
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::copy_constructible<V>
#endif
{ return base_; }
constexpr V base() && { return std::move(base_); }
constexpr auto begin()
{
constexpr format from_format = detail::format_of<detail::range_value_t<V>>();
if constexpr(detail::is_charn_view<V>) {
return make_begin<from_format>(detail::begin(base_.base()), detail::end(base_.base()));
} else {
return make_begin<from_format>(detail::begin(base_), detail::end(base_));
}
}
constexpr auto begin() const
{
constexpr format from_format = detail::format_of<detail::range_value_t<const V>>();
if constexpr(detail::is_charn_view<V>) {
return make_begin<from_format>(detail::begin(base_.base()), detail::end(base_.base()));
} else {
return make_begin<from_format>(detail::begin(base_), detail::end(base_));
}
}
constexpr auto end()
{
constexpr format from_format = detail::format_of<detail::range_value_t<V>>();
if constexpr(detail::is_charn_view<V>) {
return make_end<from_format>(detail::begin(base_.base()), detail::end(base_.base()));
} else {
return make_end<from_format>(detail::begin(base_), detail::end(base_));
}
}
constexpr auto end() const
{
constexpr format from_format = detail::format_of<detail::range_value_t<const V>>();
if constexpr(detail::is_charn_view<V>) {
return make_end<from_format>(detail::begin(base_.base()), detail::end(base_.base()));
} else {
return make_end<from_format>(detail::begin(base_), detail::end(base_));
}
}
/** Stream inserter; performs unformatted output, in UTF-8
encoding. */
friend std::ostream & operator<<(std::ostream & os, utf_view v)
{
if constexpr (Format == format::utf8) {
auto out = std::ostreambuf_iterator<char>(os);
for (auto it = v.begin(); it != v.end(); ++it, ++out) {
*out = *it;
}
} else {
boost::parser::detail::text::transcode_to_utf8(
v.begin(), v.end(), std::ostreambuf_iterator<char>(os));
}
return os;
}
#if defined(BOOST_TEXT_DOXYGEN) || defined(_MSC_VER)
/** Stream inserter; performs unformatted output, in UTF-16 encoding.
Defined on Windows only. */
friend std::wostream & operator<<(std::wostream & os, utf_view v)
{
if constexpr (Format == format::utf16) {
auto out = std::ostreambuf_iterator<wchar_t>(os);
for (auto it = v.begin(); it != v.end(); ++it, ++out) {
*out = *it;
}
} else {
boost::parser::detail::text::transcode_to_utf16(
v.begin(), v.end(), std::ostreambuf_iterator<wchar_t>(os));
}
return os;
}
#endif
};
#if BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD
template<format Format, class R>
utf_view(R &&) -> utf_view<Format, std::views::all_t<R>>;
template<class V>
using utf8_view = utf_view<format::utf8, V>;
template<class V>
using utf16_view = utf_view<format::utf16, V>;
template<class V>
using utf32_view = utf_view<format::utf32, V>;
#else
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<utf_range V>
requires std::ranges::view<V>
#else
template<typename V>
#endif
class utf8_view : public utf_view<format::utf8, V>
{
public:
constexpr utf8_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::default_initializable<V>
#endif
= default;
constexpr utf8_view(V base) :
utf_view<format::utf8, V>{std::move(base)}
{}
};
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<utf_range V>
requires std::ranges::view<V>
#else
template<typename V>
#endif
class utf16_view : public utf_view<format::utf16, V>
{
public:
constexpr utf16_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::default_initializable<V>
#endif
= default;
constexpr utf16_view(V base) :
utf_view<format::utf16, V>{std::move(base)}
{}
};
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<utf_range V>
requires std::ranges::view<V>
#else
template<typename V>
#endif
class utf32_view : public utf_view<format::utf32, V>
{
public:
constexpr utf32_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires std::default_initializable<V>
#endif
= default;
constexpr utf32_view(V base) :
utf_view<format::utf32, V>{std::move(base)}
{}
};
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class R>
utf8_view(R &&) -> utf8_view<std::views::all_t<R>>;
template<class R>
utf16_view(R &&) -> utf16_view<std::views::all_t<R>>;
template<class R>
utf32_view(R &&) -> utf32_view<std::views::all_t<R>>;
#endif
#endif
#if defined(BOOST_TEXT_DOXYGEN)
/** A view adaptor that produces a UTF-8 view of the given view. */
constexpr detail::unspecified as_utf8;
/** A view adaptor that produces a UTF-16 view of the given view. */
constexpr detail::unspecified as_utf16;
/** A view adaptor that produces a UTF-32 view of the given view. */
constexpr detail::unspecified as_utf32;
#endif
namespace detail {
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class R, template<class> class View>
concept can_utf_view = requires { View(std::declval<R>()); };
#else
template<class R, class View>
using can_utf_view_expr = decltype(View(std::declval<R>()));
template<class R, template<class> class View>
constexpr bool can_utf_view =
is_detected_v<can_utf_view_expr, R, View<R>>;
#endif
template<class T>
constexpr bool is_utf_view = false;
template<class T>
constexpr bool is_utf_view<utf8_view<T>> = true;
template<class T>
constexpr bool is_utf_view<utf16_view<T>> = true;
template<class T>
constexpr bool is_utf_view<utf32_view<T>> = true;
template<format F, class T>
constexpr bool is_utf_view<utf_view<F, T>> = true;
template<typename T>
constexpr bool is_bounded_array_v = false;
template<typename T, int N>
constexpr bool is_bounded_array_v<T[N]> = true;
template<class R>
constexpr decltype(auto) unpack_range(R && r)
{
using T = detail::remove_cv_ref_t<R>;
if constexpr (forward_range_v<T>) {
auto unpacked =
boost::parser::detail::text::unpack_iterator_and_sentinel(detail::begin(r), detail::end(r));
if constexpr (is_bounded_array_v<T>) {
constexpr auto n = std::extent_v<T>;
if (n && !r[n - 1])
--unpacked.last;
return BOOST_PARSER_DETAIL_TEXT_SUBRANGE(unpacked.first, unpacked.last);
} else if constexpr (
!std::is_same_v<decltype(unpacked.first), iterator_t<R>> ||
!std::is_same_v<decltype(unpacked.last), sentinel_t<R>>) {
return unpacking_view(std::forward<R>(r));
} else {
return std::forward<R>(r);
}
} else {
return std::forward<R>(r);
}
}
template<class R>
using unpacked_range = decltype(detail::unpack_range(std::declval<R>()));
template<template<class> class View, format Format>
struct as_utf_impl : stl_interfaces::range_adaptor_closure<as_utf_impl<View, Format>>
{
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class R>
requires is_utf_view<std::remove_cvref_t<R>> ||
(std::ranges::viewable_range<R> &&
can_utf_view<unpacked_range<R>, View>) ||
utf_pointer<std::remove_cvref_t<R>>
#else
template<typename R>
#endif
[[nodiscard]] constexpr auto operator()(R && r) const
{
using T = detail::remove_cv_ref_t<R>;
if constexpr (detail::is_empty_view<T>) {
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
return std::ranges::empty_view<format_to_type_t<Format>>{};
#else
return 42; // Never gonna happen.
#endif
} else if constexpr (is_utf_view<T>) {
return View(std::forward<R>(r).base());
} else if constexpr (detail::is_charn_view<T>) {
return View(std::forward<R>(r));
} else if constexpr (std::is_pointer_v<T>) {
return View(
BOOST_PARSER_DETAIL_TEXT_SUBRANGE(r, null_sentinel));
} else {
return View(detail::unpack_range(std::forward<R>(r)));
}
}
};
template<class T>
constexpr bool is_utf32_view = false;
template<class V>
constexpr bool is_utf32_view<utf_view<format::utf32, V>> = true;
}
inline constexpr detail::as_utf_impl<utf8_view, format::utf8> as_utf8;
inline constexpr detail::as_utf_impl<utf16_view, format::utf16> as_utf16;
inline constexpr detail::as_utf_impl<utf32_view, format::utf32> as_utf32;
}}
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
namespace std::ranges {
template<class V, auto F>
inline constexpr bool enable_borrowed_range<boost::parser::detail::text::project_view<V, F>> =
enable_borrowed_range<V>;
template<class V>
inline constexpr bool enable_borrowed_range<boost::parser::detail::text::unpacking_view<V>> =
enable_borrowed_range<V>;
template<boost::parser::detail::text::format Format, class V>
inline constexpr bool enable_borrowed_range<boost::parser::detail::text::utf_view<Format, V>> =
enable_borrowed_range<V>;
#if !BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD
template<class V>
inline constexpr bool enable_borrowed_range<boost::parser::detail::text::utf8_view<V>> =
enable_borrowed_range<V>;
template<class V>
inline constexpr bool enable_borrowed_range<boost::parser::detail::text::utf16_view<V>> =
enable_borrowed_range<V>;
template<class V>
inline constexpr bool enable_borrowed_range<boost::parser::detail::text::utf32_view<V>> =
enable_borrowed_range<V>;
#endif
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_TRIE_FWD_HPP
#define BOOST_PARSER_DETAIL_TEXT_TRIE_FWD_HPP
namespace boost::parser::detail { namespace text {
/** A statically polymorphic less-than compariason object type. This is
only necessary for pre-C++14 portablility. */
struct less
{
template<typename T>
bool operator()(T const & lhs, T const & rhs) const
{
return std::less<T>{}(lhs, rhs);
}
};
template<
typename Key,
typename Value,
typename Compare = less,
std::size_t KeySize = 0>
struct trie;
template<typename Key, typename Value, typename Compare = less>
struct trie_map;
template<typename Key, typename Compare = less>
struct trie_set;
}}
#endif

View File

@@ -1,274 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_UNPACK_HPP
#define BOOST_PARSER_DETAIL_TEXT_UNPACK_HPP
#include <boost/parser/detail/text/transcode_iterator_fwd.hpp>
#include <type_traits>
#include <optional>
namespace boost::parser::detail { namespace text {
struct no_op_repacker
{
template<class T>
T operator()(T x) const
{
return x;
}
};
namespace detail {
// Using this custom template is quite a bit faster than using lambdas.
// Unexpected.
template<
typename RepackedIterator,
typename I,
typename S,
typename Then,
bool Bidi>
struct repacker
{
repacker() = default;
#if !BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<bool Enable = Bidi, typename = std::enable_if_t<Enable>>
#endif
repacker(I first, S last, Then then)
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires Bidi
#endif
: first{first},
last{last},
then{then}
{}
#if !BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<bool Enable = !Bidi, typename = std::enable_if_t<Enable>>
#endif
repacker(S last, Then then)
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
requires(!Bidi)
#endif
:
last{last}, then{then}
{}
auto operator()(I it) const
{
if constexpr (Bidi) {
return then(RepackedIterator(*first, it, last));
} else {
return then(RepackedIterator(it, last));
}
}
std::optional<I> first;
[[no_unique_address]] S last;
[[no_unique_address]] Then then;
};
template<typename I, typename S, typename Repack>
constexpr auto
unpack_iterator_and_sentinel_impl(I first, S last, Repack repack);
template<
format FromFormat,
format ToFormat,
typename I,
typename S,
typename ErrorHandler,
typename Repack>
constexpr auto unpack_iterator_and_sentinel_impl(
utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> first,
utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> last,
Repack repack);
template<
format FromFormat,
format ToFormat,
typename I,
typename S,
typename ErrorHandler,
typename Repack>
constexpr auto unpack_iterator_and_sentinel_impl(
utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> first,
S last,
Repack repack);
template<typename I, typename S, typename Repack>
constexpr auto
unpack_iterator_and_sentinel(I first, S last, Repack repack)
{
return detail::unpack_iterator_and_sentinel_impl(
first, last, repack);
}
struct unpack_iterator_and_sentinel_cpo
{
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<
utf_iter I,
std::sentinel_for<I> S,
typename Repack = no_op_repacker>
requires std::forward_iterator<I>
#else
template<typename I, typename S, typename Repack = no_op_repacker>
#endif
constexpr auto
operator()(I first, S last, Repack repack = Repack()) const
{
return unpack_iterator_and_sentinel(first, last, repack);
}
};
}
inline namespace cpo {
inline constexpr detail::unpack_iterator_and_sentinel_cpo
unpack_iterator_and_sentinel{};
}
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<format FormatTag, utf_iter I, std::sentinel_for<I> S, class Repack>
#else
template<format FormatTag, typename I, typename S, class Repack>
#endif
struct unpack_result
{
static constexpr format format_tag = FormatTag;
I first;
[[no_unique_address]] S last;
[[no_unique_address]] Repack repack;
};
namespace detail {
struct no_such_type
{};
template<typename I, typename S, typename Repack>
constexpr auto
unpack_iterator_and_sentinel_impl(I first, S last, Repack repack)
{
using value_type = detail::iter_value_t<I>;
if constexpr (
std::is_same_v<value_type, char>
#if defined(__cpp_char8_t)
|| std::is_same_v<value_type, char8_t>
#endif
) {
return unpack_result<format::utf8, I, S, Repack>{
first, last, repack};
} else if constexpr (
#if defined(_MSC_VER)
std::is_same_v<value_type, wchar_t> ||
#endif
std::is_same_v<value_type, char16_t>) {
return unpack_result<format::utf16, I, S, Repack>{
first, last, repack};
} else if constexpr (
#if !defined(_MSC_VER)
std::is_same_v<value_type, wchar_t> ||
#endif
std::is_same_v<value_type, char32_t>) {
return unpack_result<format::utf32, I, S, Repack>{
first, last, repack};
} else {
static_assert(
std::is_same_v<Repack, no_such_type>,
"Unpacked iterator is not a utf_iter!");
return 0;
}
}
}
}}
#include <boost/parser/detail/text/transcode_iterator.hpp>
namespace boost::parser::detail { namespace text { namespace detail {
template<
format FromFormat,
format ToFormat,
typename I,
typename S,
typename ErrorHandler,
typename Repack>
constexpr auto unpack_iterator_and_sentinel_impl(
utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> first,
utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> last,
Repack repack)
{
using iterator = utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler>;
if constexpr (
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
std::bidirectional_iterator<I>
#else
std::is_base_of_v<
std::bidirectional_iterator_tag,
typename std::iterator_traits<I>::iterator_category>
#endif
) {
return boost::parser::detail::text::unpack_iterator_and_sentinel(
first.base(),
last.base(),
repacker<
iterator,
decltype(first.begin()),
decltype(first.end()),
Repack,
true>(first.begin(), first.end(), repack));
} else {
return boost::parser::detail::text::unpack_iterator_and_sentinel(
first.base(),
last.base(),
repacker<iterator, int, decltype(first.end()), Repack, false>(
first.end(), repack));
}
}
template<
format FromFormat,
format ToFormat,
typename I,
typename S,
typename ErrorHandler,
typename Repack>
constexpr auto unpack_iterator_and_sentinel_impl(
utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler> first,
S last,
Repack repack)
{
using iterator = utf_iterator<FromFormat, ToFormat, I, S, ErrorHandler>;
if constexpr (
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
std::bidirectional_iterator<I>
#else
std::is_base_of_v<
std::bidirectional_iterator_tag,
typename std::iterator_traits<I>::iterator_category>
#endif
) {
return boost::parser::detail::text::unpack_iterator_and_sentinel(
first.base(),
last,
repacker<
iterator,
decltype(first.begin()),
decltype(first.end()),
Repack,
true>(first.begin(), first.end(), repack));
} else {
return boost::parser::detail::text::unpack_iterator_and_sentinel(
first.base(),
last,
repacker<iterator, int, S, Repack, false>(last, repack));
}
}
}}}
#endif

View File

@@ -1,47 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_UTF_HPP
#define BOOST_PARSER_DETAIL_TEXT_UTF_HPP
#include <boost/parser/detail/text/config.hpp>
#include <cstdint>
#include <type_traits>
#include <cstdint>
namespace boost::parser::detail { namespace text {
/** The Unicode Transformation Formats. */
enum class format { utf8 = 1, utf16 = 2, utf32 = 4 };
namespace detail {
template<typename T>
constexpr format format_of()
{
if constexpr (
std::is_same_v<T, char>
#if defined(__cpp_char8_t)
|| std::is_same_v<T, char8_t>
#endif
) {
return format::utf8;
} else if (
std::is_same_v<T, char16_t>
#ifdef _MSC_VER
|| std::is_same_v<T, wchar_t>
#endif
) {
return format::utf16;
} else {
return format::utf32;
}
}
}
}}
#endif

View File

@@ -1,359 +0,0 @@
#ifndef BOOST_PARSER_ERROR_HANDLING_HPP
#define BOOST_PARSER_ERROR_HANDLING_HPP
#include <boost/parser/error_handling_fwd.hpp>
#include <boost/parser/detail/printing.hpp>
#include <boost/parser/detail/text/algorithm.hpp>
#include <boost/parser/detail/text/transcode_iterator.hpp>
#include <array>
#include <functional>
#include <iostream>
#include <sstream>
namespace boost { namespace parser {
namespace detail {
// All the hard line break code points from the Unicode Line Break
// Algorithm; see https://unicode.org/reports/tr14.
inline constexpr std::array<int, 7> eol_cps = {
{0x000a, 0x000b, 0x000c, 0x000d, 0x0085, 0x2028, 0x2029}};
inline constexpr int eol_cp_mask =
0x000a | 0x000b | 0x000c | 0x000d | 0x0085 | 0x2028 | 0x2029;
}
/** Returns the `line_position` for `it`, counting lines from the
beginning of the input `first`. */
template<typename Iter>
line_position<Iter> find_line_position(Iter first, Iter it)
{
bool prev_cr = false;
auto retval = line_position<Iter>{first, 0, 0};
for (Iter pos = first; pos != it; ++pos) {
auto const c = *pos;
bool const found =
(c & detail::eol_cp_mask) == c &&
std::find(detail::eol_cps.begin(), detail::eol_cps.end(), c) !=
detail::eol_cps.end();
if (found) {
retval.line_start = std::next(pos);
retval.column_number = 0;
} else {
++retval.column_number;
}
if (found && (!prev_cr || c != 0x000a))
++retval.line_number;
prev_cr = c == 0x000d;
}
return retval;
}
/** Returns the iterator to the end of the line in which `it` is
found. */
template<typename Iter, typename Sentinel>
Iter find_line_end(Iter it, Sentinel last)
{
return parser::detail::text::find_if(it, last, [](auto c) {
return (c & detail::eol_cp_mask) == c &&
std::find(
detail::eol_cps.begin(), detail::eol_cps.end(), c) !=
detail::eol_cps.end();
});
}
template<typename Iter, typename Sentinel>
std::ostream & write_formatted_message(
std::ostream & os,
std::string_view filename,
Iter first,
Iter it,
Sentinel last,
std::string_view message,
int64_t preferred_max_line_length,
int64_t max_after_caret)
{
if (!filename.empty())
os << filename << ':';
auto const position = parser::find_line_position(first, it);
os << (position.line_number + 1) << ':' << position.column_number
<< ": " << message << " here";
if (it == last)
os << " (end of input)";
os << ":\n";
std::string underlining(std::distance(position.line_start, it), ' ');
detail::trace_input(os, position.line_start, it, false, 1u << 31);
if (it == last) {
os << '\n' << underlining << "^\n";
return os;
}
underlining += '^';
int64_t const limit = (std::max)(
preferred_max_line_length,
(int64_t)underlining.size() + max_after_caret);
int64_t i = (int64_t)underlining.size();
auto const line_end = parser::find_line_end(std::next(it), last);
detail::trace_input(os, it, line_end, false, limit - i);
os << '\n' << underlining << '\n';
return os;
}
#if defined(_MSC_VER)
template<typename Iter, typename Sentinel>
std::ostream & write_formatted_message(
std::ostream & os,
std::wstring_view filename,
Iter first,
Iter it,
Sentinel last,
std::string_view message,
int64_t preferred_max_line_length,
int64_t max_after_caret)
{
auto const r = filename | parser::detail::text::as_utf8;
std::string s(r.begin(), r.end());
return parser::write_formatted_message(
os,
s,
first,
it,
last,
message,
preferred_max_line_length,
max_after_caret);
}
#endif
template<typename Iter, typename Sentinel>
std::ostream & write_formatted_expectation_failure_error_message(
std::ostream & os,
std::string_view filename,
Iter first,
Sentinel last,
parse_error<Iter> const & e,
int64_t preferred_max_line_length,
int64_t max_after_caret)
{
std::string message = "error: Expected ";
message += e.what();
return parser::write_formatted_message(
os,
filename,
first,
e.iter,
last,
message,
preferred_max_line_length,
max_after_caret);
}
#if defined(_MSC_VER)
template<typename Iter, typename Sentinel>
std::ostream & write_formatted_expectation_failure_error_message(
std::ostream & os,
std::wstring_view filename,
Iter first,
Sentinel last,
parse_error<Iter> const & e,
int64_t preferred_max_line_length,
int64_t max_after_caret)
{
auto const r = filename | parser::detail::text::as_utf8;
std::string s(r.begin(), r.end());
return parser::write_formatted_expectation_failure_error_message(
os, s, first, last, e, preferred_max_line_length, max_after_caret);
}
#endif
/** An error handler that allows users to supply callbacks to handle the
reporting of warnings and errors. The reporting of errors and/or
warnings can be suppressed by supplying one or both
default-constructed callbacks. */
struct callback_error_handler
{
using callback_type = std::function<void(std::string const &)>;
callback_error_handler() {}
callback_error_handler(
callback_type error,
callback_type warning = callback_type(),
std::string_view filename = "") :
error_(error), warning_(warning), filename_(filename)
{}
#if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN)
/** This overload is Windows-only. */
callback_error_handler(
callback_type error,
callback_type warning,
std::wstring_view filename) :
error_(error), warning_(warning)
{
auto const r = filename | parser::detail::text::as_utf8;
filename_.assign(r.begin(), r.end());
}
#endif
template<typename Iter, typename Sentinel>
error_handler_result
operator()(Iter first, Sentinel last, parse_error<Iter> const & e) const
{
if (error_) {
std::stringstream ss;
parser::write_formatted_expectation_failure_error_message(
ss, filename_, first, last, e);
error_(ss.str());
}
return error_handler_result::fail;
}
template<typename Context, typename Iter>
void diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context,
Iter it) const
{
callback_type const & cb =
kind == diagnostic_kind::error ? error_ : warning_;
if (!cb)
return;
std::stringstream ss;
parser::write_formatted_message(
ss,
filename_,
parser::_begin(context),
it,
parser::_end(context),
message);
cb(ss.str());
}
template<typename Context>
void diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context) const
{
diagnose(kind, message, context, parser::_where(context).begin());
}
callback_type error_;
callback_type warning_;
std::string filename_;
};
/** An error handler that just re-throws any exception generated by the
parse. */
struct rethrow_error_handler
{
template<typename Iter, typename Sentinel>
error_handler_result
operator()(Iter first, Sentinel last, parse_error<Iter> const & e) const
{
return error_handler_result::rethrow;
}
template<typename Context, typename Iter>
void diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context,
Iter it) const
{}
template<typename Context>
void diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context) const
{}
};
// implementations
template<typename Iter, typename Sentinel>
error_handler_result default_error_handler::operator()(
Iter first, Sentinel last, parse_error<Iter> const & e) const
{
parser::write_formatted_expectation_failure_error_message(
std::cerr, "", first, last, e);
return error_handler_result::fail;
}
template<typename Context, typename Iter>
void default_error_handler::diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context,
Iter it) const
{
parser::write_formatted_message(
std::cerr,
"",
parser::_begin(context),
it,
parser::_end(context),
message);
}
template<typename Context>
void default_error_handler::diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context) const
{
diagnose(kind, message, context, parser::_where(context).begin());
}
template<typename Iter, typename Sentinel>
error_handler_result stream_error_handler::operator()(
Iter first, Sentinel last, parse_error<Iter> const & e) const
{
std::ostream * os = err_os_;
if (!os)
os = &std::cerr;
parser::write_formatted_expectation_failure_error_message(
*os, filename_, first, last, e);
return error_handler_result::fail;
}
template<typename Context, typename Iter>
void stream_error_handler::diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context,
Iter it) const
{
std::ostream * os = kind == diagnostic_kind::error ? err_os_ : warn_os_;
if (!os)
os = &std::cerr;
parser::write_formatted_message(
*os,
filename_,
parser::_begin(context),
it,
parser::_end(context),
message);
}
template<typename Context>
void stream_error_handler::diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context) const
{
diagnose(kind, message, context, parser::_where(context).begin());
}
}}
#endif

View File

@@ -1,230 +0,0 @@
#ifndef BOOST_PARSER_ERROR_HANDLING_FWD_HPP
#define BOOST_PARSER_ERROR_HANDLING_FWD_HPP
#include <boost/parser/config.hpp>
#include <boost/parser/detail/text/transcode_view.hpp>
#include <iostream>
#include <string_view>
namespace boost { namespace parser {
/** The possible actions to take when a parse error is handled by an error
handler. */
enum class error_handler_result {
fail, /// Fail the top-level parse.
rethrow /// Re-throw the parse error exception.
};
/** The exception thrown when a parse error is encountered, consisting of
an iterator to the point of failure, and the name of the failed parser
or rule in `what()`. */
template<typename Iter>
struct parse_error : std::runtime_error
{
parse_error(Iter it, std::string const & msg) :
runtime_error(msg), iter(it)
{}
Iter iter;
};
/** A position within a line, consisting of an iterator to the start of
the line, the line number, and the column number. */
template<typename Iter>
struct line_position
{
Iter line_start;
int64_t line_number;
int64_t column_number;
};
/** Writes a formatted message (meaning prefixed with the file name, line,
and column number) to `os`. */
template<typename Iter, typename Sentinel>
std::ostream & write_formatted_message(
std::ostream & os,
std::string_view filename,
Iter first,
Iter it,
Sentinel last,
std::string_view message,
int64_t preferred_max_line_length = 80,
int64_t max_after_caret = 40);
#if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN)
/** Writes a formatted message (meaning prefixed with the file name, line,
and column number) to `os`. This overload is Windows-only. */
template<typename Iter, typename Sentinel>
std::ostream & write_formatted_message(
std::ostream & os,
std::wstring_view filename,
Iter first,
Iter it,
Sentinel last,
std::string_view message,
int64_t preferred_max_line_length = 80,
int64_t max_after_caret = 40);
#endif
/** Writes a formatted parse-expectation failure (meaning prefixed with
the file name, line, and column number) to `os`. */
template<typename Iter, typename Sentinel>
std::ostream & write_formatted_expectation_failure_error_message(
std::ostream & os,
std::string_view filename,
Iter first,
Sentinel last,
parse_error<Iter> const & e,
int64_t preferred_max_line_length = 80,
int64_t max_after_caret = 40);
#if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN)
/** Writes a formatted parse-expectation failure (meaning prefixed with
the file name, line, and column number) to `os`. This overload is
Windows-only. */
template<typename Iter, typename Sentinel>
std::ostream & write_formatted_expectation_failure_error_message(
std::ostream & os,
std::wstring_view filename,
Iter first,
Sentinel last,
parse_error<Iter> const & e,
int64_t preferred_max_line_length = 80,
int64_t max_after_caret = 40);
#endif
/** The kinds of diagnostics that can be handled by an error handler. */
enum class diagnostic_kind {
error, /// An error diagnostic.
warning /// A warning diagnostic.
};
/** The error handler used when the user does not specify a custom one.
This error handler prints warnings and errors to `std::cerr`, and does
not have an associcated filename. */
struct default_error_handler
{
constexpr default_error_handler() = default;
/** Handles a `parse_error` exception thrown during parsing. A
formatted parse-expectation failure is printed to `std::cerr`.
Always returns `error_handler_result::fail`. */
template<typename Iter, typename Sentinel>
error_handler_result operator()(
Iter first, Sentinel last, parse_error<Iter> const & e) const;
/** Prints `message` to `std::cerr`. The diagnostic is printed with
the given `kind`, indicating the location as being at `it`. This
must be called within a parser semantic action, providing the
parse context. */
//[ error_handler_api_1
template<typename Context, typename Iter>
void diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context,
Iter it) const;
//]
/** Prints `message` to `std::cerr`. The diagnostic is printed with
the given `kind`, at no particular location. This must be called
within a parser semantic action, providing the parse context. */
//[ error_handler_api_2
template<typename Context>
void diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context) const;
//]
};
/** Prints warnings and errors to the `std::ostream`s provided by the
user, or `std::cerr` if neither stream is specified. If a filename is
provided, that is used to print all diagnostics. */
struct stream_error_handler
{
stream_error_handler() : err_os_(&std::cerr), warn_os_(err_os_) {}
stream_error_handler(std::string_view filename) :
filename_(filename), err_os_(&std::cerr), warn_os_(err_os_)
{}
stream_error_handler(std::string_view filename, std::ostream & errors) :
filename_(filename), err_os_(&errors), warn_os_(&errors)
{}
stream_error_handler(
std::string_view filename,
std::ostream & errors,
std::ostream & warnings) :
filename_(filename), err_os_(&errors), warn_os_(&warnings)
{}
#if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN)
/** This overload is Windows-only. */
stream_error_handler(std::wstring_view filename) :
err_os_(&std::cerr), warn_os_(err_os_)
{
auto const r = filename | detail::text::as_utf8;
filename_.assign(r.begin(), r.end());
}
/** This overload is Windows-only. */
stream_error_handler(
std::wstring_view filename, std::ostream & errors) :
err_os_(&errors), warn_os_(&errors)
{
auto const r = filename | detail::text::as_utf8;
filename_.assign(r.begin(), r.end());
}
/** This overload is Windows-only. */
stream_error_handler(
std::wstring_view filename,
std::ostream & errors,
std::ostream & warnings) :
err_os_(&errors), warn_os_(&warnings)
{
auto const r = filename | detail::text::as_utf8;
filename_.assign(r.begin(), r.end());
}
#endif
/** Handles a `parse_error` exception thrown during parsing. A
formatted parse-expectation failure is printed to `*err_os_` when
`err_os_` is non-null, or `std::cerr` otherwise. Always returns
`error_handler_result::fail`. */
template<typename Iter, typename Sentinel>
error_handler_result
operator()(Iter first, Sentinel last, parse_error<Iter> const & e) const;
/** Let `std::ostream * s = kind == diagnostic_kind::error : err_os_ :
warn_os_`; prints `message` to `*s` when `s` is non-null, or
`std::cerr` otherwise. The diagnostic is printed with the given
`kind`, indicating the location as being at `it`. This must be
called within a parser semantic action, providing the parse
context. */
template<typename Context, typename Iter>
void diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context,
Iter it) const;
/** Let `std::ostream * s = kind == diagnostic_kind::error : err_os_ :
warn_os_`; prints `message` to `*s` when `s` is non-null, or
`std::cerr` otherwise. The diagnostic is printed with the given
`kind`, at no particular location. This must be called within a
parser semantic action, providing the parse context. */
template<typename Context>
void diagnose(
diagnostic_kind kind,
std::string_view message,
Context const & context) const;
private:
std::string filename_;
std::ostream * err_os_;
std::ostream * warn_os_;
};
}}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,489 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_PARSER_FWD_HPP
#define BOOST_PARSER_PARSER_FWD_HPP
#include <boost/parser/config.hpp>
#include <boost/parser/error_handling_fwd.hpp>
#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <variant>
namespace boost::parser::detail { namespace text {
struct null_sentinel_t;
}}
namespace boost { namespace parser {
/** A sentinel type that compares equal to a pointer to a character value
type, iff the pointer is null. */
using null_sentinel_t = boost::parser::detail::text::null_sentinel_t;
/** A variable template that indicates that type `T` is an optional-like
type. */
template<typename T>
constexpr bool enable_optional = false;
#ifndef BOOST_PARSER_DOXYGEN
template<typename T>
constexpr bool enable_optional<std::optional<T>> = true;
#endif
namespace detail {
template<typename T>
constexpr bool is_optional_v = enable_optional<T>;
struct nope;
enum class flags : unsigned int {
gen_attrs = 1 << 0,
use_skip = 1 << 1,
trace = 1 << 2,
in_apply_parser = 1 << 3
};
struct any_copyable
{
template<
typename T,
typename Enable = std::enable_if_t<!std::is_reference_v<T>>>
any_copyable(T && v) :
impl_(new holder<std::decay_t<T>>(std::move(v)))
{}
template<typename T>
any_copyable(T const & v) : impl_(new holder<T>(v))
{}
any_copyable() = default;
any_copyable(any_copyable const & other)
{
if (other.impl_)
impl_ = other.impl_->clone();
}
any_copyable & operator=(any_copyable const & other)
{
any_copyable temp(other);
swap(temp);
return *this;
}
any_copyable(any_copyable &&) = default;
any_copyable & operator=(any_copyable &&) = default;
bool empty() const { return impl_.get() == nullptr; }
template<typename T>
T & cast() const
{
BOOST_PARSER_DEBUG_ASSERT(impl_);
BOOST_PARSER_DEBUG_ASSERT(dynamic_cast<holder<T> *>(impl_.get()));
return static_cast<holder<T> *>(impl_.get())->value_;
}
void swap(any_copyable & other) { std::swap(impl_, other.impl_); }
private:
struct holder_base
{
virtual ~holder_base() {}
virtual std::unique_ptr<holder_base> clone() const = 0;
};
template<typename T>
struct holder : holder_base
{
holder(T && v) : value_(std::move(v)) {}
holder(T const & v) : value_(v) {}
virtual ~holder() {}
virtual std::unique_ptr<holder_base> clone() const
{
return std::unique_ptr<holder_base>(new holder<T>{value_});
}
T value_;
};
std::unique_ptr<holder_base> impl_;
};
using symbol_table_tries_t =
std::map<void *, any_copyable, std::less<void *>>;
template<typename Iter, typename Sentinel, typename ErrorHandler>
inline auto make_context(
Iter first,
Sentinel last,
bool & success,
int & indent,
ErrorHandler const & error_handler,
nope &,
symbol_table_tries_t & symbol_table_tries) noexcept;
struct skip_skipper;
}
/** Repeats the application of another parser `p` of type `Parser`,
optionally applying another parser `d` of type `DelimiterParser` in
between each pair of applications of `p`. The parse succeeds if `p`
succeeds at least the minumum number of times, and `d` succeeds each
time it is applied. The attribute produced is a sequence of the type
of attribute produced by `Parser`. */
template<
typename Parser,
typename DelimiterParser = detail::nope,
typename MinType = int64_t,
typename MaxType = int64_t>
struct repeat_parser;
/** Repeats the application of another parser `p` of type `Parser`, `[0,
Inf)` times. The parse always succeeds. The attribute produced is a
sequence of the type of attribute produced by `Parser`. */
template<typename Parser>
struct zero_plus_parser;
/** Repeats the application of another parser `p` of type `Parser`, `[1,
Inf)` times. The parse succeeds iff `p` succeeds at least once. The
attribute produced is a sequence of the type of attribute produced by
`Parser`. */
template<typename Parser>
struct one_plus_parser;
/** Repeats the application of another parser `p` of type `Parser`, `[1,
Inf)` times, applying a parser `d` of type `DelimiterParser` in
between each pair of applications of `p`. The parse succeeds iff `p`
succeeds at least once, and `d` succeeds each time it is applied. The
attribute produced is a sequence of the type of attribute produced by
`Parser`. */
template<typename Parser, typename DelimiterParser>
struct delimited_seq_parser;
/** Repeats the application of another parser of type `Parser`, `[0, 1]`
times. The parse always succeeds. The attribute produced is a
`std::optional<T>`, where `T` is the type of attribute produced by
`Parser`. */
template<typename Parser>
struct opt_parser;
/** Applies each parser in `ParserTuple`, in order, stopping after the
application of the first one that succeeds. The parse succeeds iff
one of the sub-parsers succeeds. The attribute produced is a
`std::variant` over the types of attribute produced by the parsers in
`ParserTuple`. */
template<typename ParserTuple>
struct or_parser;
/** Applies each parser in `ParserTuple`, in order. The parse succeeds
iff all of the sub-parsers succeed. The attribute produced is a
`std::tuple` over the types of attribute produced by the parsers in
`ParserTuple`. The BacktrackingTuple template parameter is a
`parser::tuple` of `std::bool_constant` values. The `i`th such value
indicates whether backtracking is allowed if the `i`th parser
fails. */
template<
typename ParserTuple,
typename BacktrackingTuple,
typename CombiningGroups>
struct seq_parser;
/** Applies the given parser `p` of type `Parser` and an invocable `a` of
type `Action`. `Action` shall model `semantic_action`, and `a` will
only be invoked if `p` succeeds. The parse succeeds iff `p` succeeds.
Produces no attribute. */
template<typename Parser, typename Action>
struct action_parser;
/** Applies the given parser `p` of type `Parser`. This parser produces
no attribute, and suppresses the production of any attributes that
would otherwise be produced by `p`. The parse succeeds iff `p`
succeeds. */
template<typename Parser>
struct omit_parser;
/** Applies the given parser `p` of type `Parser`; regardless of the
attribute produced by `Parser`, this parser's attribute is equivalent
to `_where(ctx)` within a semantic action on `p`. The parse succeeds
iff `p` succeeds. */
template<typename Parser>
struct raw_parser;
#if defined(BOOST_PARSER_DOXYGEN) || defined(__cpp_lib_concepts)
/** Applies the given parser `p` of type `Parser`. Regardless of the
attribute produced by `Parser`, this parser's attribute is equivalent
to `std::basic_string_view<char_type>` within a semantic action on
`p`, where `char_type` is the type of character in the sequence being
parsed. If the parsed range is transcoded, `char_type` will be the
type being transcoded from. If the underlying range of `char_type` is
non-contiguous, code using `string_view_parser` is ill-formed. The
parse succeeds iff `p` succeeds. This parser is only available in
C++20 and later. */
template<typename Parser>
struct string_view_parser;
#endif
/** Applies the given parser `p` of type `Parser`, disabling the current
skipper in use, if any. The parse succeeds iff `p` succeeds. The
attribute produced is the type of attribute produced by `Parser`. */
template<typename Parser>
struct lexeme_parser;
/** Applies the given parser `p` of type `Parser`, enabling
case-insensitive matching, based on Unicode case folding. The parse
succeeds iff `p` succeeds. The attribute produced is the type of
attribute produced by `Parser`. */
template<typename Parser>
struct no_case_parser;
/** Applies the given parser `p` of type `Parser`, using a parser of type
`SkipParser` as the skipper. The parse succeeds iff `p` succeeds.
The attribute produced is the type of attribute produced by
`Parser`. */
template<typename Parser, typename SkipParser = detail::nope>
struct skip_parser;
/** Applies the given parser `p` of type `Parser`, producing no attributes
and consuming no input. The parse succeeds iff `p`'s success is
unequal to `FailOnMatch`. */
template<typename Parser, bool FailOnMatch>
struct expect_parser;
/** Matches one of a set S of possible inputs, each of which is associated
with an attribute value of type `T`, forming a symbol table. New
elements and their associated attributes may be added to or removed
from S dynamically, during parsing; any such changes are reverted at
the end of parsing. The parse succeeds iff an element of S is
matched. \see `symbols` */
template<typename T>
struct symbol_parser;
/** Applies another parser `p`, associated with this parser via `TagType`.
The attribute produced is `Attribute`. Both a default-constructed
object of type `LocalState`, and a default-constructed object of type
`ParamsTuple`, are added to the parse context before the associated
parser is applied. The parse succeeds iff `p` succeeds. If
`CanUseCallbacks` is `true`, and if this parser is used within a call
to `callback_parse()`, the attribute is produced via callback;
otherwise, the attribute is produced as normal (as a return value, or
as an out-param). The rule may be constructed with a user-friendly
name that will appear if the top-level parse is executed with
`trace_mode == boost::parser::trace::on`. */
template<
bool CanUseCallbacks,
typename TagType,
typename Attribute,
typename LocalState,
typename ParamsTuple>
struct rule_parser;
/** Matches anything, and consumes no input. If `Predicate` is anything
other than `detail::nope` (which it is by default), and `pred_(ctx)`
evaluates to false, where `ctx` is the parser context, the parse
fails. */
template<typename Predicate>
struct eps_parser;
/** Matches only the end of input. Produces no attribute. */
struct eoi_parser;
/** Matches anything, consumes no input, and produces an attribute of type
`RESOLVE(Attribute)`. */
template<typename Attribute>
struct attr_parser;
/** Matches a single code point. If `AttributeType` is not `void`,
`AttributeType` is the attribute type produced; otherwise, the
attribute type is the decayed type of the matched code point. The
parse fails only if the parser is constructed with a specific set of
expected code point values that does not include the matched code
point. */
template<typename Expected, typename AttributeType = void>
struct char_parser;
/** Maches a particular string, delimited by an iterator sentinel pair;
produces no attribute. */
template<typename StrIter, typename StrSentinel>
struct string_parser;
/** Maches an end-of-line (`NewlinesOnly == true`) or whitespace
(`NewlinesOnly == false`) code point, based on the Unicode definitions
of each (also matches the two code points `"\r\n"`). Produces no
attribute. */
template<bool NewlinesOnly>
struct ws_parser;
/** Maches the strings "true" and "false", producing an attribute of
`true` or `false`, respectively, and fails on any other input. */
struct bool_parser;
/** Matches an unsigned number of radix `Radix`, of at least `MinDigits`
and at most `MaxDigits`, producing an attribute of type `T`. Fails on
any other input. The parse will also fail if `Expected` is anything
but `detail::nope` (which it is by default), and the produced
attribute is not equal to `expected_`. `Radix` must be in `[2,
36]`. */
template<
typename T,
int Radix = 10,
int MinDigits = 1,
int MaxDigits = -1,
typename Expected = detail::nope>
struct uint_parser;
/** Matches a signed number of radix `Radix`, of at least `MinDigits` and
at most `MaxDigits`, producing an attribute of type `T`. Fails on any
other input. The parse will also fail if `Expected` is anything but
`detail::nope` (which it is by default), and the produced
attribute is not equal to `expected_`. `Radix` must be one of `2`,
`8`, `10`, or `16`. */
template<
typename T,
int Radix = 10,
int MinDigits = 1,
int MaxDigits = -1,
typename Expected = detail::nope>
struct int_parser;
/** Matches a floating point number, producing an attribute of type
`T`. */
template<typename T>
struct float_parser;
/** Applies at most one of the parsers in `OrParser`. If `switch_value_`
matches one or more of the values in the parsers in `OrParser`, the
first such parser is applied, and the success or failure and attribute
of the parse are those of the applied parser. Otherwise, the parse
fails. */
template<typename SwitchValue, typename OrParser = detail::nope>
struct switch_parser;
/** A wrapper for parsers that provides the operations that must be
supported by all parsers (e.g. `operator>>()`). `GlobalState` is an
optional state object that can be accessed within semantic actions via
a call to `_globals()`. This global state object is ignored for all
but the topmost parser; the topmost global state object is available
in the semantic actions of all nested parsers. `ErrorHandler` is the
type of the error handler to be used on parse failure. This handler
is ignored on all but the topmost parser; the topmost parser's error
handler is used for all errors encountered during parsing. */
template<
typename Parser,
typename GlobalState = detail::nope,
typename ErrorHandler = default_error_handler>
struct parser_interface;
using no_attribute = detail::nope;
using no_local_state = detail::nope;
using no_params = detail::nope;
/** A type used to declare named parsing rules. The `TagType` template
parameter is used to associate a particular `rule` with the
`rule_parser` used during parsing. */
template<
typename TagType,
typename Attribute = no_attribute,
typename LocalState = no_local_state,
typename ParamsTuple = no_params>
struct rule;
/** A type used to declare named parsing rules that support reporting of
attributes via callback. The `TagType` template parameter is used to
associate a particular `rule` with the `rule_parser` used during
parsing. */
template<
typename TagType,
typename Attribute = no_attribute,
typename LocalState = no_local_state,
typename ParamsTuple = no_params>
struct callback_rule;
/** Returns a reference to the attribute(s) (i.e. return value) of the
bottommost parser; multiple attributes will be stored within a
`parser::tuple`. You may write to this value in a semantic action to
control what attribute value(s) the associated parser produces.
Returns `none` if the bottommost parser does produce an attribute. */
template<typename Context>
decltype(auto) _val(Context const & context);
/** Returns a reference to the attribute or attributes already produced by
the bottommost parser; multiple attributes will be stored within a
`parser::tuple`. Returns `none` if the bottommost parser does produce
an attribute. */
template<typename Context>
decltype(auto) _attr(Context const & context);
/** Returns a `subrange` that describes the matched range of the
bottommost parser. */
template<typename Context>
decltype(auto) _where(Context const & context);
/** Returns an iterator to the beginning of the entire sequence being
parsed. The effect of calling this within a semantic action
associated with a skip-parser is undefined */
template<typename Context>
decltype(auto) _begin(Context const & context);
/** Returns an iterator to the end of the entire sequence being parsed. */
template<typename Context>
decltype(auto) _end(Context const & context);
/** Returns a reference to a `bool` that represents the success or failure
of the bottommost parser. You can assign `false` to this within a
semantic action to force a parser to fail its parse. */
template<typename Context>
decltype(auto) _pass(Context const & context);
/** Returns a reference to one or more local values that the bottommost
rule is declared to have; multiple values will be stored within a
`parser::tuple`. Returns `none` if there is no bottommost rule, or if
that rule has no locals. */
template<typename Context>
decltype(auto) _locals(Context const & context);
/** Returns a reference to one or more parameters passed to the bottommost
rule `r`, by using `r` as `r.with(param0, param1, ... paramN)`;
multiple values will be stored within a `parser::tuple`. Returns
`none` if there is no bottommost rule, or if that rule was not given
any parameters. */
template<typename Context>
decltype(auto) _params(Context const & context);
/** Returns a reference to the globals object associated with the
top-level parser. Returns `none` if there is no associated globals
object. */
template<typename Context>
decltype(auto) _globals(Context const & context);
/** Returns a reference to the error handler object associated with the
top-level parser. Returns `none` if there is no associated error
handler. */
template<typename Context>
decltype(auto) _error_handler(Context const & context);
/** Report that the error described in `message` occurred at `location`,
using the context's error handler. */
template<typename Iter, typename Context>
void _report_error(
Context const & context, std::string_view message, Iter location);
/** Report that the error described in `message` occurred at
`_where(context).begin()`, using the context's error handler. */
template<typename Context>
void _report_error(Context const & context, std::string_view message);
/** Report that the warning described in `message` occurred at `location`,
using the context's error handler. */
template<typename Iter, typename Context>
void _report_warning(
Context const & context, std::string_view message, Iter location);
/** Report that the warning described in `message` occurred at
`_where(context).begin()`, using the context's error handler. */
template<typename Context>
void _report_warning(Context const & context, std::string_view message);
}}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,109 +0,0 @@
// Copyright (C) 2022 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_SUBRANGE_HPP
#define BOOST_PARSER_SUBRANGE_HPP
#include <boost/parser/detail/text/config.hpp>
#include <boost/parser/detail/text/detail/algorithm.hpp>
#include <boost/parser/detail/stl_interfaces/view_interface.hpp>
namespace boost::parser {
/** A simple view type used throughout the rest of the library in C++17
builds; similar to `std::ranges::subrange`. */
#if BOOST_PARSER_USE_CONCEPTS
template<std::forward_iterator I, std::sentinel_for<I> S = I>
#else
template<typename I, typename S = I>
#endif
struct subrange : detail::stl_interfaces::view_interface<subrange<I, S>>
{
constexpr subrange() = default;
constexpr subrange(I first, S last) : first_(first), last_(last) {}
template<typename R>
constexpr explicit subrange(R const & r) :
first_(detail::text::detail::begin(r)),
last_(detail::text::detail::end(r))
{}
constexpr I begin() const { return first_; }
constexpr S end() const { return last_; }
[[nodiscard]] constexpr subrange next(std::ptrdiff_t n = 1) const
{
return subrange{detail::text::detail::next(first_), last_};
}
[[nodiscard]] constexpr subrange prev(std::ptrdiff_t n = 1) const
{
return subrange{detail::text::detail::prev(first_), last_};
}
constexpr subrange & advance(std::ptrdiff_t n)
{
std::advance(first_, n);
return *this;
}
template<
typename I2,
typename S2,
typename Enable = std::enable_if_t<
std::is_convertible<I, I2>::value &&
std::is_convertible<S, S2>::value>>
constexpr operator subrange<I2, S2>() const
{
return {first_, last_};
}
private:
I first_;
[[no_unique_address]] S last_;
};
#if defined(__cpp_deduction_guides)
#if BOOST_PARSER_USE_CONCEPTS
template<std::input_or_output_iterator I, std::sentinel_for<I> S>
#else
template<typename I, typename S>
#endif
subrange(I, S) -> subrange<I, S>;
#if BOOST_PARSER_USE_CONCEPTS
template<std::ranges::borrowed_range R>
#else
template<typename R>
#endif
subrange(R &&) -> subrange<
detail::text::detail::iterator_t<R>,
detail::text::detail::sentinel_t<R>>;
#endif
/** Makes a `subrange<I, S>` from an `I` and an `S`. */
#if BOOST_PARSER_USE_CONCEPTS
template<std::forward_iterator I, std::sentinel_for<I> S = I>
#else
template<typename I, typename S = I>
#endif
constexpr subrange<I, S> make_subrange(I first, S last) noexcept
{
return subrange<I, S>(first, last);
}
}
#if BOOST_PARSER_USE_CONCEPTS
namespace std::ranges {
template<std::forward_iterator I, std::sentinel_for<I> S>
inline constexpr bool enable_borrowed_range<boost::parser::subrange<I, S>> =
true;
}
#endif
#endif

View File

@@ -1,107 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_TRANSCODE_VIEW_HPP
#define BOOST_PARSER_TRANSCODE_VIEW_HPP
#include <boost/parser/detail/text/transcode_view.hpp>
namespace boost::parser {
using format = detail::text::format;
#if BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD
template<class V>
using utf8_view = detail::text::utf_view<format::utf8, V>;
template<class V>
using utf16_view = detail::text::utf_view<format::utf16, V>;
template<class V>
using utf32_view = detail::text::utf_view<format::utf32, V>;
#else
/** A view that produces UTF-8 from an given sequence of UTF. */
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS || defined(BOOST_PARSER_DOXYGEN)
template<detail::text::utf_range V>
requires std::ranges::view<V>
#else
template<typename V>
#endif
class utf8_view : public detail::text::utf_view<format::utf8, V>
{
public:
constexpr utf8_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS || defined(BOOST_PARSER_DOXYGEN)
requires std::default_initializable<V>
#endif
= default;
constexpr utf8_view(V base) :
detail::text::utf_view<format::utf8, V>{std::move(base)}
{}
};
/** A view that produces UTF-16 from an given sequence of UTF. */
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS || defined(BOOST_PARSER_DOXYGEN)
template<detail::text::utf_range V>
requires std::ranges::view<V>
#else
template<typename V>
#endif
class utf16_view : public detail::text::utf_view<format::utf16, V>
{
public:
constexpr utf16_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS || defined(BOOST_PARSER_DOXYGEN)
requires std::default_initializable<V>
#endif
= default;
constexpr utf16_view(V base) :
detail::text::utf_view<format::utf16, V>{std::move(base)}
{}
};
/** A view that produces UTF-32 from an given sequence of UTF. */
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS || defined(BOOST_PARSER_DOXYGEN)
template<detail::text::utf_range V>
requires std::ranges::view<V>
#else
template<typename V>
#endif
class utf32_view : public detail::text::utf_view<format::utf32, V>
{
public:
constexpr utf32_view()
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS || defined(BOOST_PARSER_DOXYGEN)
requires std::default_initializable<V>
#endif
= default;
constexpr utf32_view(V base) :
detail::text::utf_view<format::utf32, V>{std::move(base)}
{}
};
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
template<class R>
utf8_view(R &&) -> utf8_view<std::views::all_t<R>>;
template<class R>
utf16_view(R &&) -> utf16_view<std::views::all_t<R>>;
template<class R>
utf32_view(R &&) -> utf32_view<std::views::all_t<R>>;
#endif
#endif
/** A view adaptor that produces a `utf8_view` of the given view. */
inline constexpr auto as_utf8 = detail::text::as_utf8;
/** A view adaptor that produces a `utf16_view` of the given view. */
inline constexpr auto as_utf16 = detail::text::as_utf16;
/** A view adaptor that produces a `utf32_view` of the given view. */
inline constexpr auto as_utf32 = detail::text::as_utf32;
}
#endif

View File

@@ -1,346 +0,0 @@
// Copyright (C) 2020 T. Zachary Laine
// Copyright Louis Dionne 2013-2017
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_TUPLE_HPP
#define BOOST_PARSER_TUPLE_HPP
#include <boost/parser/config.hpp>
#include <boost/parser/detail/detection.hpp>
#if BOOST_PARSER_USE_STD_TUPLE
#include <tuple>
#else
// Silence very verbose warnings about std::is_pod/std::is_literal being
// deprecated.
#if defined(__GNUC__) || defined(__clang__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
# pragma GCC diagnostic ignored "-Wunused-value"
#endif
#include <boost/hana.hpp>
#if defined(__GNUC__) || defined(__clang__)
# pragma GCC diagnostic pop
#endif
#endif
namespace boost { namespace parser {
namespace detail {
// to_int() and parse_llong() taken from boost/hana/bool.hpp.
constexpr int to_int(char c)
{
int result = 0;
if (c >= 'A' && c <= 'F') {
result = static_cast<int>(c) - static_cast<int>('A') + 10;
} else if (c >= 'a' && c <= 'f') {
result = static_cast<int>(c) - static_cast<int>('a') + 10;
} else {
result = static_cast<int>(c) - static_cast<int>('0');
}
return result;
}
template<std::size_t N>
constexpr long long parse_llong(const char (&arr)[N])
{
long long base = 10;
std::size_t offset = 0;
if constexpr (N > 2) {
bool starts_with_zero = arr[0] == '0';
bool is_hex = starts_with_zero && arr[1] == 'x';
bool is_binary = starts_with_zero && arr[1] == 'b';
if (is_hex) {
// 0xDEADBEEF (hexadecimal)
base = 16;
offset = 2;
} else if (is_binary) {
// 0b101011101 (binary)
base = 2;
offset = 2;
} else if (starts_with_zero) {
// 012345 (octal)
base = 8;
offset = 1;
}
}
long long number = 0;
long long multiplier = 1;
for (std::size_t i = 0; i < N - offset; ++i) {
char c = arr[N - 1 - i];
if (c != '\'') { // skip digit separators
number += to_int(c) * multiplier;
multiplier *= base;
}
}
return number;
}
}
/** The tuple template alias used within Boost.Parser. This will be
`boost::hana::tuple` unless `BOOST_PARSER_DISABLE_HANA_TUPLE` is
defined, in which case it is `std::tuple`. */
#if BOOST_PARSER_USE_STD_TUPLE
template<typename... Args>
using tuple = std::tuple<Args...>;
#else
template<typename... Args>
using tuple = hana::tuple<Args...>;
#endif
/** A template alias that is `boost::hana::integral_constant<T, I>` unless
`BOOST_PARSER_DISABLE_HANA_TUPLE` is defined, in which case it is
`std::integral_constant<T, I>`. */
#if BOOST_PARSER_USE_STD_TUPLE
template<typename T, T I>
using integral_constant = std::integral_constant<T, I>;
#else
template<typename T, T I>
using integral_constant = hana::integral_constant<T, I>;
#endif
/** An accessor that returns a reference to the `I`-th data member of an
aggregate struct or `boost::parser::tuple`. */
template<typename T, typename U, U I>
constexpr decltype(auto) get(T && x, integral_constant<U, I> i);
/** A template alias that is `boost::hana::llong<I>` unless
`BOOST_PARSER_DISABLE_HANA_TUPLE` is defined, in which case it is
`std::integral_constant<long long, I>`. */
template<long long I>
using llong = integral_constant<long long, I>;
namespace literals {
/** A literal that can be used to concisely name `parser::llong`
integral constants. */
template<char... chars>
constexpr auto operator"" _c()
{
constexpr long long n =
detail::parse_llong<sizeof...(chars)>({chars...});
return llong<n>{};
}
}
namespace detail {
/** A tuple accessor that returns a reference to the `I`-th element. */
template<typename T, T I, typename... Args>
constexpr decltype(auto)
tuple_get(tuple<Args...> const & t, integral_constant<T, I>)
{
#if BOOST_PARSER_USE_STD_TUPLE
return std::get<I>(t);
#else
return hana::at_c<I>(t);
#endif
}
/** A tuple accessor that returns a reference to the `I`-th element. */
template<typename T, T I, typename... Args>
constexpr decltype(auto)
tuple_get(tuple<Args...> & t, integral_constant<T, I>)
{
#if BOOST_PARSER_USE_STD_TUPLE
return std::get<I>(t);
#else
return hana::at_c<I>(t);
#endif
}
/** A tuple accessor that returns a reference to the `I`-th element. */
template<typename T, T I, typename... Args>
constexpr decltype(auto)
tuple_get(tuple<Args...> && t, integral_constant<T, I>)
{
#if BOOST_PARSER_USE_STD_TUPLE
return std::move(std::get<I>(t));
#else
return std::move(hana::at_c<I>(t));
#endif
}
template<int N>
struct ce_int
{
constexpr static int value = N;
};
struct whatever
{
int _;
template<typename T>
operator T() const && noexcept
{
#if defined(__GNUC__) && __GNUC__ < 13
// Yuck.
std::remove_reference_t<T> * ptr = nullptr;
ptr += 1; // warning mitigation
return *ptr;
#else
return std::declval<T>();
#endif
}
};
template<typename T, int... Is>
constexpr auto
constructible_expr_impl(std::integer_sequence<int, Is...>)
-> decltype(T{whatever{Is}...}, ce_int<1>{});
template<typename T, typename N>
using constructible_expr = decltype(detail::constructible_expr_impl<T>(
std::make_integer_sequence<int, N::value>()));
template<typename T, int... Is>
constexpr int struct_arity_impl(std::integer_sequence<int, Is...>)
{
return (
detected_or_t<ce_int<0>, constructible_expr, T, ce_int<Is>>::
value +
... + 0);
}
// This often mistakenly returns 1 when you give it a struct with
// private/protected members, because of copy/move construction.
// Fortunately, we don't care -- we never assign from tuples of size
// 1.
template<typename T>
constexpr int struct_arity_v =
detail::struct_arity_impl<T>(std::make_integer_sequence<
int,
BOOST_PARSER_MAX_AGGREGATE_SIZE>()) -
1;
template<typename T>
constexpr int tuple_size_ = -1;
template<typename... Elems>
constexpr int tuple_size_<tuple<Elems...>> = sizeof...(Elems);
template<typename T, typename Tuple, int... Is>
auto assign_tuple_to_aggregate(
T & x, Tuple tup, std::integer_sequence<int, Is...>)
-> decltype(x = T{parser::get(std::move(tup), llong<Is>{})...});
template<typename T, typename Tuple, int... Is>
auto tuple_to_aggregate(Tuple && tup, std::integer_sequence<int, Is...>)
-> decltype(T{std::move(parser::get(tup, llong<Is>{}))...})
{
return T{std::move(parser::get(tup, llong<Is>{}))...};
}
template<typename T, typename Tuple>
using tuple_to_aggregate_expr =
decltype(detail::assign_tuple_to_aggregate(
std::declval<T &>(),
std::declval<Tuple>(),
std::make_integer_sequence<int, tuple_size_<Tuple>>()));
template<typename Struct, typename Tuple>
constexpr bool is_struct_assignable_v =
struct_arity_v<Struct> == tuple_size_<Tuple>
? is_detected_v<tuple_to_aggregate_expr, Struct, Tuple>
: false;
template<int N>
struct tie_aggregate_impl
{
template<typename T>
static constexpr auto call(T & x)
{
static_assert(
sizeof(T) && false,
"It looks like you're trying to use a struct larger than "
"the limit.");
}
};
template<typename T>
constexpr auto tie_aggregate(T & x)
{
static_assert(!std::is_union_v<T>);
return tie_aggregate_impl<struct_arity_v<T>>::call(x);
}
template<typename Tuple, typename Tie, int... Is>
auto aggregate_to_tuple(
Tuple & tup, Tie tie, std::integer_sequence<int, Is...>)
-> decltype((
(parser::get(tup, llong<Is>{}) =
std::move(parser::get(tie, llong<Is>{}))),
...,
(void)0))
{
return (
(parser::get(tup, llong<Is>{}) =
std::move(parser::get(tie, llong<Is>{}))),
...,
(void)0);
}
template<typename Tuple, typename T>
using aggregate_to_tuple_expr = decltype(detail::aggregate_to_tuple(
std::declval<Tuple &>(),
detail::tie_aggregate(std::declval<T &>()),
std::make_integer_sequence<int, tuple_size_<Tuple>>()));
template<typename Tuple, typename Struct>
constexpr bool is_tuple_assignable_impl()
{
if constexpr (
std::is_aggregate_v<Struct> &&
struct_arity_v<Struct> == tuple_size_<Tuple>) {
return is_detected_v<aggregate_to_tuple_expr, Tuple, Struct>;
} else {
return false;
}
}
template<typename Tuple, typename Struct>
constexpr bool
is_tuple_assignable_v = is_tuple_assignable_impl<Tuple, Struct>();
template<typename T>
struct is_tuple : std::false_type
{};
template<typename... T>
struct is_tuple<tuple<T...>> : std::true_type
{};
}
template<typename T, typename U, U I>
constexpr decltype(auto) get(T && x, integral_constant<U, I> i)
{
using just_t = std::decay_t<T>;
if constexpr (detail::is_tuple<just_t>::value) {
return detail::tuple_get((T &&) x, i);
} else if constexpr (std::is_aggregate_v<just_t>) {
auto tup = detail::tie_aggregate(x);
return detail::tuple_get(tup, i);
} else {
static_assert(
sizeof(T) != sizeof(T),
"boost::parser::get() is only defined for boost::parser::tuple "
"and aggregate structs.");
}
}
}}
#include <boost/parser/detail/aggr_to_tuple_generated.hpp>
#endif