mirror of
https://github.com/boostorg/parser.git
synced 2026-01-20 16:52:13 +00:00
Compare commits
3 Commits
develop
...
single_hea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20b017c965 | ||
|
|
c4d9e4fbcd | ||
|
|
c68897b9e6 |
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
26333
include/boost/parser/parser_unified.hpp
Normal file
26333
include/boost/parser/parser_unified.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user