mirror of
https://github.com/boostorg/spirit.git
synced 2026-01-19 04:42:11 +00:00
Modernize char/string, use X3's own char_encoding
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -7,62 +8,56 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ANY_CHAR_APRIL_16_2006_1051AM)
|
||||
#define BOOST_SPIRIT_X3_ANY_CHAR_APRIL_16_2006_1051AM
|
||||
|
||||
#include <boost/type_traits/extent.hpp>
|
||||
#include <boost/spirit/home/x3/char/literal_char.hpp>
|
||||
#include <boost/spirit/home/x3/char/char_set.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
template <typename Encoding>
|
||||
struct any_char : char_parser<any_char<Encoding>>
|
||||
{
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef char_type attribute_type;
|
||||
static bool const has_attribute = true;
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = char_type;
|
||||
static constexpr bool has_attribute = true;
|
||||
|
||||
template <typename Char, typename Context>
|
||||
bool test(Char ch_, Context const&) const
|
||||
template <typename Context>
|
||||
[[nodiscard]] static constexpr bool test(char_type ch, Context const&) noexcept
|
||||
{
|
||||
return encoding::ischar(ch_);
|
||||
return encoding::ischar(ch);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
constexpr literal_char<Encoding> operator()(Char ch) const
|
||||
[[nodiscard]] static constexpr literal_char<Encoding> operator()(char_type ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
constexpr literal_char<Encoding> operator()(const Char (&ch)[2]) const
|
||||
[[nodiscard]] static constexpr literal_char<Encoding> operator()(char_type const (&ch)[2]) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <typename Char, std::size_t N>
|
||||
constexpr char_set<Encoding> operator()(const Char (&ch)[N]) const
|
||||
template <std::size_t N>
|
||||
[[nodiscard]] static constexpr char_set<Encoding> operator()(char_type const (&ch)[N]) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
constexpr char_range<Encoding> operator()(Char from, Char to) const
|
||||
[[nodiscard]] static constexpr char_range<Encoding> operator()(char_type from, char_type to) noexcept
|
||||
{
|
||||
return { from, to };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
constexpr char_range<Encoding> operator()(Char (&from)[2], Char (&to)[2]) const
|
||||
[[nodiscard]] static constexpr char_range<Encoding> operator()(char_type const (&from)[2], char_type const (&to)[2]) noexcept
|
||||
{
|
||||
return { static_cast<char_type>(from[0]), static_cast<char_type>(to[0]) };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
char_set<Encoding> operator()(std::basic_string<Char> const& s) const
|
||||
[[nodiscard]] static char_set<Encoding> operator()(std::basic_string_view<char_type> sv) noexcept
|
||||
{
|
||||
return { s };
|
||||
return { std::move(sv) };
|
||||
}
|
||||
};
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -8,84 +9,139 @@
|
||||
#define BOOST_SPIRIT_X3_CHAR_APRIL_16_2006_1051AM
|
||||
|
||||
#include <boost/spirit/home/x3/char/any_char.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
|
||||
#include <boost/spirit/home/x3/char/literal_char.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/string_traits.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/ascii.hpp> // deprecated
|
||||
#include <boost/spirit/home/x3/char_encoding/iso8859_1.hpp> // deprecated
|
||||
#include <boost/spirit/home/x3/char_encoding/standard.hpp>
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
# include <boost/spirit/home/x3/char_encoding/standard_wide.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
namespace standard
|
||||
{
|
||||
typedef any_char<char_encoding::standard> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
inline constexpr any_char<char_encoding::standard> char_{};
|
||||
|
||||
constexpr literal_char<char_encoding::standard, unused_type>
|
||||
lit(char ch)
|
||||
inline namespace helpers
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard, unused_type>
|
||||
lit(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
constexpr literal_char<char_encoding::standard, unused_type>
|
||||
lit(wchar_t ch)
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard, unused_type>
|
||||
lit(traits::X3VagueArrayOf2Chars<char> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
} // helpers
|
||||
|
||||
// If you see "no matching overload" on string literals (e.g. `"foo"`),
|
||||
// you may need to include `x3/string/literal_string.hpp`.
|
||||
// If you still see errors after the inclusion, that might be due to
|
||||
// mixing incompatible string literals. Don't do that.
|
||||
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
}
|
||||
|
||||
using standard::char_type;
|
||||
using standard::char_;
|
||||
using standard::lit;
|
||||
inline constexpr auto const& char_ = standard::char_; // TODO: this can't overload other character types
|
||||
using standard::helpers::lit;
|
||||
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
typedef any_char<char_encoding::standard_wide> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
inline constexpr any_char<char_encoding::standard_wide> char_{};
|
||||
|
||||
constexpr literal_char<char_encoding::standard_wide, unused_type>
|
||||
lit(wchar_t ch)
|
||||
inline namespace helpers
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard_wide, unused_type>
|
||||
lit(wchar_t ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard_wide, unused_type>
|
||||
lit(traits::X3VagueArrayOf2Chars<wchar_t> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
} // helpers
|
||||
|
||||
constexpr void lit(traits::CharIncompatibleWith<wchar_t> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<wchar_t> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
}
|
||||
|
||||
using standard_wide::helpers::lit;
|
||||
#endif
|
||||
|
||||
namespace ascii
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
namespace unicode
|
||||
{
|
||||
typedef any_char<char_encoding::ascii> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
inline constexpr any_char<char_encoding::unicode> char_{};
|
||||
|
||||
constexpr literal_char<char_encoding::ascii, unused_type>
|
||||
lit(char ch)
|
||||
inline namespace helpers
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
// TODO: add `char8_t` and `char16_t` overloads
|
||||
|
||||
constexpr literal_char<char_encoding::ascii, unused_type>
|
||||
lit(wchar_t ch)
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::unicode, unused_type>
|
||||
lit(char32_t ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::unicode, unused_type>
|
||||
lit(traits::X3VagueArrayOf2Chars<char32_t> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
} // helpers
|
||||
|
||||
constexpr void lit(traits::CharIncompatibleWith<char32_t> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<char32_t> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
}
|
||||
|
||||
namespace iso8859_1
|
||||
using unicode::helpers::lit;
|
||||
#endif
|
||||
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] ascii
|
||||
{
|
||||
typedef any_char<char_encoding::iso8859_1> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
inline constexpr any_char<char_encoding::ascii> char_{};
|
||||
|
||||
constexpr literal_char<char_encoding::iso8859_1, unused_type>
|
||||
lit(char ch)
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::ascii, unused_type>
|
||||
lit(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
constexpr literal_char<char_encoding::iso8859_1, unused_type>
|
||||
lit(wchar_t ch)
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
}
|
||||
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] iso8859_1
|
||||
{
|
||||
inline constexpr any_char<char_encoding::iso8859_1> char_{};
|
||||
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::iso8859_1, unused_type>
|
||||
lit(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto const*) = delete; // Mixing incompatible character types is not allowed
|
||||
constexpr void lit(traits::CharIncompatibleWith<char> auto) = delete; // Mixing incompatible character types is not allowed
|
||||
}
|
||||
|
||||
namespace extension
|
||||
@@ -93,29 +149,23 @@ namespace boost { namespace spirit { namespace x3
|
||||
template <>
|
||||
struct as_parser<char>
|
||||
{
|
||||
typedef literal_char<
|
||||
char_encoding::standard, unused_type>
|
||||
type;
|
||||
using type = literal_char<char_encoding::standard, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(char ch)
|
||||
[[nodiscard]] static constexpr type call(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
template <>
|
||||
struct as_parser<wchar_t>
|
||||
{
|
||||
typedef literal_char<
|
||||
char_encoding::standard_wide, unused_type>
|
||||
type;
|
||||
using type = literal_char<char_encoding::standard_wide, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(wchar_t ch)
|
||||
[[nodiscard]] static constexpr type call(wchar_t ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
@@ -125,37 +175,30 @@ namespace boost { namespace spirit { namespace x3
|
||||
template <>
|
||||
struct as_parser<char [2]>
|
||||
{
|
||||
typedef literal_char<
|
||||
char_encoding::standard, unused_type>
|
||||
type;
|
||||
using type = literal_char<char_encoding::standard, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(char const ch[])
|
||||
[[nodiscard]] static constexpr type call(char const ch[]) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
template <>
|
||||
struct as_parser<wchar_t [2]>
|
||||
{
|
||||
typedef literal_char<
|
||||
char_encoding::standard_wide, unused_type>
|
||||
type;
|
||||
using type = literal_char<char_encoding::standard_wide, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(wchar_t const ch[] )
|
||||
[[nodiscard]] static constexpr type call(wchar_t const ch[]) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -8,24 +9,27 @@
|
||||
#define BOOST_SPIRIT_X3_CHAR_CLASS_APRIL_16_2006_1051AM
|
||||
|
||||
#include <boost/spirit/home/x3/char/char_parser.hpp>
|
||||
#include <boost/spirit/home/x3/char/detail/cast_char.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/x3/char/char_class_tags.hpp>
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
#include <boost/spirit/home/x3/char/detail/cast_char.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard_wide.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/iso8859_1.hpp>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Encoding>
|
||||
struct char_class_base
|
||||
{
|
||||
typedef typename Encoding::classify_type char_type;
|
||||
using char_type = typename Encoding::classify_type;
|
||||
|
||||
#define BOOST_SPIRIT_X3_CLASSIFY(name) \
|
||||
template <typename Char> \
|
||||
static bool \
|
||||
is(name##_tag, Char ch) \
|
||||
[[nodiscard]] static constexpr bool \
|
||||
is(name##_tag, Char ch) noexcept \
|
||||
{ \
|
||||
return Encoding::is##name \
|
||||
BOOST_PREVENT_MACRO_SUBSTITUTION \
|
||||
@@ -51,31 +55,29 @@ namespace boost { namespace spirit { namespace x3
|
||||
};
|
||||
|
||||
template <typename Encoding, typename Tag>
|
||||
struct char_class
|
||||
: char_parser<char_class<Encoding, Tag>>
|
||||
struct char_class : char_parser<char_class<Encoding, Tag>>
|
||||
{
|
||||
typedef Encoding encoding;
|
||||
typedef Tag tag;
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef char_type attribute_type;
|
||||
static bool const has_attribute = true;
|
||||
using encoding = Encoding;
|
||||
using tag = Tag;
|
||||
using char_type = typename Encoding::char_type;
|
||||
using attribute_type = char_type;
|
||||
static constexpr bool has_attribute = true;
|
||||
|
||||
template <typename Char, typename Context>
|
||||
bool test(Char ch, Context const& context) const
|
||||
[[nodiscard]] constexpr bool test(Char ch, Context const& context) const noexcept
|
||||
{
|
||||
return encoding::ischar(ch)
|
||||
&& char_class_base<Encoding>::is(
|
||||
get_case_compare<Encoding>(context).get_char_class_tag(tag()), ch);
|
||||
x3::get_case_compare<Encoding>(context).get_char_class_tag(tag()), ch);
|
||||
}
|
||||
};
|
||||
|
||||
#define BOOST_SPIRIT_X3_CHAR_CLASS(encoding, name) \
|
||||
typedef char_class<char_encoding::encoding, name##_tag> name##_type; \
|
||||
constexpr name##_type name = name##_type(); \
|
||||
/***/
|
||||
using name##_type = char_class<char_encoding::encoding, name##_tag>; \
|
||||
inline constexpr name##_type name{};
|
||||
|
||||
#define BOOST_SPIRIT_X3_CHAR_CLASSES(encoding) \
|
||||
namespace encoding \
|
||||
#define BOOST_SPIRIT_X3_CHAR_CLASSES(ns_attr, encoding) \
|
||||
namespace ns_attr encoding \
|
||||
{ \
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(encoding, alnum) \
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(encoding, alpha) \
|
||||
@@ -89,44 +91,46 @@ namespace boost { namespace spirit { namespace x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(encoding, space) \
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(encoding, blank) \
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(encoding, upper) \
|
||||
} \
|
||||
/***/
|
||||
}
|
||||
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(standard)
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(standard_wide)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(, standard)
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(, standard_wide)
|
||||
#endif
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(ascii)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES(iso8859_1)
|
||||
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES([[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]], ascii)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASSES([[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]], iso8859_1)
|
||||
|
||||
#undef BOOST_SPIRIT_X3_CHAR_CLASS
|
||||
#undef BOOST_SPIRIT_X3_CHAR_CLASSES
|
||||
|
||||
using standard::alnum_type;
|
||||
using standard::alpha_type;
|
||||
using standard::digit_type;
|
||||
using standard::xdigit_type;
|
||||
using standard::cntrl_type;
|
||||
using standard::graph_type;
|
||||
using standard::lower_type;
|
||||
using standard::print_type;
|
||||
using standard::punct_type;
|
||||
using standard::space_type;
|
||||
using standard::blank_type;
|
||||
using standard::upper_type;
|
||||
using alnum_type = standard::alnum_type;
|
||||
using alpha_type = standard::alpha_type;
|
||||
using digit_type = standard::digit_type;
|
||||
using xdigit_type = standard::xdigit_type;
|
||||
using cntrl_type = standard::cntrl_type;
|
||||
using graph_type = standard::graph_type;
|
||||
using lower_type = standard::lower_type;
|
||||
using print_type = standard::print_type;
|
||||
using punct_type = standard::punct_type;
|
||||
using space_type = standard::space_type;
|
||||
using blank_type = standard::blank_type;
|
||||
using upper_type = standard::upper_type;
|
||||
|
||||
using standard::alnum;
|
||||
using standard::alpha;
|
||||
using standard::digit;
|
||||
using standard::xdigit;
|
||||
using standard::cntrl;
|
||||
using standard::graph;
|
||||
using standard::lower;
|
||||
using standard::print;
|
||||
using standard::punct;
|
||||
using standard::space;
|
||||
using standard::blank;
|
||||
using standard::upper;
|
||||
}}}
|
||||
inline constexpr auto const& alnum = standard::alnum;
|
||||
inline constexpr auto const& alpha = standard::alpha;
|
||||
inline constexpr auto const& digit = standard::digit;
|
||||
inline constexpr auto const& xdigit = standard::xdigit;
|
||||
inline constexpr auto const& cntrl = standard::cntrl;
|
||||
inline constexpr auto const& graph = standard::graph;
|
||||
inline constexpr auto const& lower = standard::lower;
|
||||
inline constexpr auto const& print = standard::print;
|
||||
inline constexpr auto const& punct = standard::punct;
|
||||
inline constexpr auto const& space = standard::space;
|
||||
inline constexpr auto const& blank = standard::blank;
|
||||
inline constexpr auto const& upper = standard::upper;
|
||||
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,29 +15,26 @@
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The base char_parser
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Derived>
|
||||
struct char_parser : parser<Derived>
|
||||
{
|
||||
template <typename Iterator, typename Context, typename Attribute>
|
||||
bool parse(
|
||||
Iterator& first, Iterator const& last
|
||||
, Context const& context, unused_type, Attribute& attr) const
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Attribute>
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
It& first, Se const& last, Context const& context, unused_type, Attribute& attr
|
||||
) const // I (saki7) don't think this can ever be noexcept, due to the nature of the operations below
|
||||
{
|
||||
x3::skip_over(first, last, context);
|
||||
if (first != last && this->derived().test(*first, context))
|
||||
{
|
||||
x3::traits::move_to(std::iter_value_t<Iterator>{*first}, attr);
|
||||
x3::traits::move_to(std::iter_value_t<It>{*first}, attr);
|
||||
++first;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -9,72 +10,73 @@
|
||||
|
||||
#include <boost/spirit/home/x3/char/char_parser.hpp>
|
||||
#include <boost/spirit/home/x3/char/detail/cast_char.hpp>
|
||||
#include <boost/spirit/home/x3/char/detail/basic_chset.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/string_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/utf8.hpp>
|
||||
#include <boost/spirit/home/x3/support/no_case.hpp>
|
||||
#include <boost/spirit/home/support/char_set/basic_chset.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Parser for a character range
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Encoding, typename Attribute = typename Encoding::char_type>
|
||||
struct char_range
|
||||
: char_parser< char_range<Encoding, Attribute> >
|
||||
struct char_range : char_parser<char_range<Encoding, Attribute>>
|
||||
{
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = Attribute;
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef Attribute attribute_type;
|
||||
static bool const has_attribute =
|
||||
!is_same<unused_type, attribute_type>::value;
|
||||
|
||||
|
||||
constexpr char_range(char_type from_, char_type to_)
|
||||
: from(from_), to(to_) {}
|
||||
constexpr char_range(char_type from_, char_type to_) noexcept
|
||||
: from(from_), to(to_)
|
||||
{}
|
||||
|
||||
template <typename Char, typename Context>
|
||||
bool test(Char ch_, Context const& context) const
|
||||
requires (std::is_convertible_v<std::remove_cvref_t<Char>, char_type>)
|
||||
[[nodiscard]] constexpr bool test(Char ch_, Context const& context) const noexcept
|
||||
{
|
||||
|
||||
char_type ch = char_type(ch_); // optimize for token based parsing
|
||||
return (get_case_compare<encoding>(context)(ch, from) >= 0)
|
||||
&& (get_case_compare<encoding>(context)(ch , to) <= 0);
|
||||
char_type ch = static_cast<char_type>(ch_); // optimize for token based parsing
|
||||
return (x3::get_case_compare<encoding>(context)(ch, from) >= 0)
|
||||
&& (x3::get_case_compare<encoding>(context)(ch , to) <= 0);
|
||||
}
|
||||
|
||||
char_type from, to;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Parser for a character set
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Encoding, typename Attribute = typename Encoding::char_type>
|
||||
struct char_set : char_parser<char_set<Encoding, Attribute>>
|
||||
{
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef Attribute attribute_type;
|
||||
static bool const has_attribute =
|
||||
!is_same<unused_type, attribute_type>::value;
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = Attribute;
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
|
||||
template <typename String>
|
||||
char_set(String const& str)
|
||||
template<std::ranges::forward_range R>
|
||||
constexpr char_set(R const& str)
|
||||
noexcept(detail::cast_char_noexcept<std::ranges::range_value_t<R>, char_type>)
|
||||
{
|
||||
using spirit::x3::detail::cast_char;
|
||||
static_assert(detail::cast_char_viable<std::ranges::range_value_t<R>, char_type>);
|
||||
|
||||
auto* definition = traits::get_c_string(str);
|
||||
auto ch = *definition++;
|
||||
while (ch)
|
||||
using detail::cast_char; // ADL introduction
|
||||
|
||||
for (auto definition = std::ranges::begin(str); definition != std::ranges::end(str);)
|
||||
{
|
||||
auto next = *definition++;
|
||||
if (next == '-')
|
||||
auto const ch = *definition;
|
||||
auto next_definition = std::next(definition);
|
||||
if (next_definition == std::ranges::end(str))
|
||||
{
|
||||
next = *definition++;
|
||||
if (next == 0)
|
||||
chset.set(cast_char<char_type>(ch));
|
||||
break;
|
||||
}
|
||||
auto next_ch = *next_definition;
|
||||
if (next_ch == '-')
|
||||
{
|
||||
next_definition = std::next(next_definition);
|
||||
if (next_definition == std::ranges::end(str))
|
||||
{
|
||||
chset.set(cast_char<char_type>(ch));
|
||||
chset.set('-');
|
||||
@@ -82,46 +84,47 @@ namespace boost { namespace spirit { namespace x3
|
||||
}
|
||||
chset.set(
|
||||
cast_char<char_type>(ch),
|
||||
cast_char<char_type>(next)
|
||||
cast_char<char_type>(*next_definition)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
chset.set(cast_char<char_type>(ch));
|
||||
}
|
||||
ch = next;
|
||||
definition = next_definition;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char, typename Context>
|
||||
bool test(Char ch_, Context const& context) const
|
||||
[[nodiscard]] constexpr bool test(Char ch_, Context const& context) const noexcept
|
||||
{
|
||||
return get_case_compare<encoding>(context).in_set(ch_, chset);
|
||||
return x3::get_case_compare<encoding>(context).in_set(ch_, chset);
|
||||
}
|
||||
|
||||
support::detail::basic_chset<char_type> chset;
|
||||
detail::basic_chset<char_type> chset;
|
||||
};
|
||||
|
||||
template <typename Encoding, typename Attribute>
|
||||
struct get_info<char_set<Encoding, Attribute>>
|
||||
{
|
||||
typedef std::string result_type;
|
||||
std::string operator()(char_set<Encoding, Attribute> const& /* p */) const
|
||||
using result_type = std::string;
|
||||
[[nodiscard]] constexpr std::string operator()(char_set<Encoding, Attribute> const& /* p */) const
|
||||
{
|
||||
return "char-set";
|
||||
return "char-set"; // TODO: make more user-friendly
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Encoding, typename Attribute>
|
||||
struct get_info<char_range<Encoding, Attribute>>
|
||||
{
|
||||
typedef std::string result_type;
|
||||
std::string operator()(char_range<Encoding, Attribute> const& p) const
|
||||
using result_type = std::string;
|
||||
[[nodiscard]] constexpr std::string operator()(char_range<Encoding, Attribute> const& p) const
|
||||
{
|
||||
return "char_range \"" + to_utf8(Encoding::toucs4(p.from)) + '-' + to_utf8(Encoding::toucs4(p.to))+ '"';
|
||||
// TODO: make more user-friendly && make the format consistent with above
|
||||
return "char_range \"" + x3::to_utf8(Encoding::toucs4(p.from)) + '-' + x3::to_utf8(Encoding::toucs4(p.to))+ '"';
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
{
|
||||
// basic character set implementation using range_run
|
||||
// basic character set implementation using char_range_run
|
||||
template <typename CharT>
|
||||
struct basic_chset
|
||||
{
|
||||
@@ -78,7 +78,7 @@ namespace boost::spirit::x3::detail
|
||||
constexpr basic_chset&
|
||||
operator|=(basic_chset const& x) noexcept
|
||||
{
|
||||
typedef typename range_run<CharT>::const_iterator const_iterator;
|
||||
typedef typename char_range_run<CharT>::const_iterator const_iterator;
|
||||
for (const_iterator iter = x.rr.begin(); iter != x.rr.end(); ++iter)
|
||||
rr.set(*iter);
|
||||
return *this;
|
||||
@@ -100,7 +100,7 @@ namespace boost::spirit::x3::detail
|
||||
constexpr basic_chset&
|
||||
operator-=(basic_chset const& x) noexcept
|
||||
{
|
||||
typedef typename range_run<CharT>::const_iterator const_iterator;
|
||||
typedef typename char_range_run<CharT>::const_iterator const_iterator;
|
||||
for (const_iterator iter = x.rr.begin(); iter != x.rr.end(); ++iter)
|
||||
rr.clear(*iter);
|
||||
return *this;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -9,27 +10,33 @@
|
||||
|
||||
#include <boost/spirit/home/x3/char/char_parser.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/utf8.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
template <typename Encoding, typename Attribute = typename Encoding::char_type>
|
||||
struct literal_char : char_parser<literal_char<Encoding, Attribute>>
|
||||
{
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef Attribute attribute_type;
|
||||
static bool const has_attribute =
|
||||
!is_same<unused_type, attribute_type>::value;
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = Attribute;
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
|
||||
template <typename Char>
|
||||
constexpr literal_char(Char ch)
|
||||
: ch(static_cast<char_type>(ch)) {}
|
||||
requires std::convertible_to<Char, char_type>
|
||||
constexpr literal_char(Char ch) noexcept
|
||||
: ch(static_cast<char_type>(ch))
|
||||
{
|
||||
static_assert(std::same_as<char_type, Char>, "Mixing incompatible character types is not allowed");
|
||||
}
|
||||
|
||||
template <typename Char, typename Context>
|
||||
bool test(Char ch_, Context const& context) const
|
||||
[[nodiscard]] constexpr bool test(Char ch_, Context const& context) const noexcept
|
||||
{
|
||||
return get_case_compare<encoding>(context)(ch, char_type(ch_)) == 0;
|
||||
static_assert(std::same_as<char_type, Char>, "Mixing incompatible character types is not allowed");
|
||||
return x3::get_case_compare<encoding>(context)(ch, char_type(ch_)) == 0;
|
||||
}
|
||||
|
||||
char_type ch;
|
||||
@@ -38,12 +45,12 @@ namespace boost { namespace spirit { namespace x3
|
||||
template <typename Encoding, typename Attribute>
|
||||
struct get_info<literal_char<Encoding, Attribute>>
|
||||
{
|
||||
typedef std::string result_type;
|
||||
std::string operator()(literal_char<Encoding, Attribute> const& p) const
|
||||
using result_type = std::string;
|
||||
[[nodiscard]] std::string operator()(literal_char<Encoding, Attribute> const& p) const
|
||||
{
|
||||
return '\'' + to_utf8(Encoding::toucs4(p.ch)) + '\'';
|
||||
return '\'' + x3::to_utf8(Encoding::toucs4(p.ch)) + '\'';
|
||||
}
|
||||
};
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -8,15 +9,12 @@
|
||||
#define BOOST_SPIRIT_X3_UNICODE_JAN_20_2012_1218AM
|
||||
|
||||
#include <boost/spirit/home/x3/char/char_parser.hpp>
|
||||
#include <boost/spirit/home/x3/char/char.hpp>
|
||||
#include <boost/spirit/home/x3/char/detail/cast_char.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/unicode.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
struct char_tag;
|
||||
struct alnum_tag;
|
||||
struct alpha_tag;
|
||||
@@ -31,9 +29,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
struct lower_tag;
|
||||
struct upper_tag;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
struct letter_tag {};
|
||||
struct mark_tag {};
|
||||
struct number_tag {};
|
||||
@@ -42,9 +38,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
struct punctuation_tag {};
|
||||
struct symbol_tag {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode General Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode General Categories
|
||||
struct uppercase_letter_tag {};
|
||||
struct lowercase_letter_tag {};
|
||||
struct titlecase_letter_tag {};
|
||||
@@ -82,9 +76,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
struct modifier_symbol_tag {};
|
||||
struct other_symbol_tag {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Derived Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Derived Categories
|
||||
struct alphabetic_tag {};
|
||||
struct uppercase_tag {};
|
||||
struct lowercase_tag {};
|
||||
@@ -93,9 +85,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
struct noncharacter_code_point_tag {};
|
||||
struct default_ignorable_code_point_tag {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Scripts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Scripts
|
||||
struct adlam_tag {};
|
||||
struct caucasian_albanian_tag {};
|
||||
struct ahom_tag {};
|
||||
@@ -262,11 +252,10 @@ namespace boost { namespace spirit { namespace x3
|
||||
struct common_tag {};
|
||||
struct unknown_tag {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct unicode_char_class_base
|
||||
{
|
||||
typedef char_encoding::unicode encoding;
|
||||
typedef char_encoding::unicode::char_type char_type;
|
||||
using encoding = char_encoding::unicode;
|
||||
using char_type = char_encoding::unicode::char_type;
|
||||
|
||||
#define BOOST_SPIRIT_X3_BASIC_CLASSIFY(name) \
|
||||
template <typename Char> \
|
||||
@@ -291,9 +280,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
/***/
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(char)
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(alnum)
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(alpha)
|
||||
@@ -308,9 +295,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(blank)
|
||||
BOOST_SPIRIT_X3_BASIC_CLASSIFY(upper)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
BOOST_SPIRIT_X3_CLASSIFY(letter)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(mark)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(number)
|
||||
@@ -319,9 +304,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
BOOST_SPIRIT_X3_CLASSIFY(punctuation)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(symbol)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode General Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode General Categories
|
||||
BOOST_SPIRIT_X3_CLASSIFY(uppercase_letter)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(lowercase_letter)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(titlecase_letter)
|
||||
@@ -359,9 +342,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
BOOST_SPIRIT_X3_CLASSIFY(modifier_symbol)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(other_symbol)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Derived Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Derived Categories
|
||||
BOOST_SPIRIT_X3_CLASSIFY(alphabetic)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(uppercase)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(lowercase)
|
||||
@@ -370,9 +351,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
BOOST_SPIRIT_X3_CLASSIFY(noncharacter_code_point)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(default_ignorable_code_point)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Scripts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Scripts
|
||||
BOOST_SPIRIT_X3_CLASSIFY(adlam)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(caucasian_albanian)
|
||||
BOOST_SPIRIT_X3_CLASSIFY(ahom)
|
||||
@@ -545,34 +524,28 @@ namespace boost { namespace spirit { namespace x3
|
||||
|
||||
template <typename Tag>
|
||||
struct unicode_char_class
|
||||
: char_parser<unicode_char_class<Tag>>
|
||||
: char_parser<unicode_char_class<Tag>>
|
||||
{
|
||||
typedef char_encoding::unicode encoding;
|
||||
typedef Tag tag;
|
||||
typedef typename encoding::char_type char_type;
|
||||
typedef char_type attribute_type;
|
||||
static bool const has_attribute = true;
|
||||
using encoding = char_encoding::unicode;
|
||||
using tag = Tag;
|
||||
using char_type = typename encoding::char_type;
|
||||
using attribute_type = char_type;
|
||||
static constexpr bool has_attribute = true;
|
||||
|
||||
template <typename Char, typename Context>
|
||||
bool test(Char ch, Context const&) const
|
||||
[[nodiscard]] constexpr bool test(Char ch, Context const&) const noexcept
|
||||
{
|
||||
return encoding::ischar(ch) && unicode_char_class_base::is(tag(), ch);
|
||||
return encoding::ischar(ch) && unicode_char_class_base::is(tag{}, ch);
|
||||
}
|
||||
};
|
||||
|
||||
#define BOOST_SPIRIT_X3_CHAR_CLASS(name) \
|
||||
typedef unicode_char_class<name##_tag> name##_type; \
|
||||
constexpr name##_type name = name##_type(); \
|
||||
/***/
|
||||
using name##_type = unicode_char_class<name##_tag>; \
|
||||
inline constexpr name##_type name{};
|
||||
|
||||
namespace unicode
|
||||
{
|
||||
typedef any_char<char_encoding::unicode> char_type;
|
||||
constexpr auto char_ = char_type{};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(alnum)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(alpha)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(digit)
|
||||
@@ -586,9 +559,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(blank)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(upper)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Major Categories
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(letter)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(mark)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(number)
|
||||
@@ -597,9 +568,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(punctuation)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(symbol)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode General Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode General Categories
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(uppercase_letter)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(lowercase_letter)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(titlecase_letter)
|
||||
@@ -637,9 +606,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(modifier_symbol)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(other_symbol)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Derived Categories
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Derived Categories
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(alphabetic)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(uppercase)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(lowercase)
|
||||
@@ -648,9 +615,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(noncharacter_code_point)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(default_ignorable_code_point)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Scripts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Unicode Scripts
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(adlam)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(caucasian_albanian)
|
||||
BOOST_SPIRIT_X3_CHAR_CLASS(ahom)
|
||||
@@ -820,6 +785,6 @@ namespace boost { namespace spirit { namespace x3
|
||||
|
||||
#undef BOOST_SPIRIT_X3_CHAR_CLASS
|
||||
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
45
include/boost/spirit/home/x3/core/config.hpp
Normal file
45
include/boost/spirit/home/x3/core/config.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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_SPIRIT_X3_CORE_CONFIG_HPP
|
||||
#define BOOST_SPIRIT_X3_CORE_CONFIG_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#if _MSC_VER
|
||||
# include <CppCoreCheck/Warnings.h>
|
||||
# pragma warning(default: CPPCORECHECK_LIFETIME_WARNINGS)
|
||||
#endif
|
||||
|
||||
// <https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c++20-[[no_unique_address]]>
|
||||
|
||||
#if _MSC_VER && _MSC_VER < 1929 // VS 2019 v16.9 or before
|
||||
# error "Too old MSVC version; we don't support this because it leads to ODR violation regarding the existence of [[(msvc::)no_unique_address]]"
|
||||
#endif
|
||||
|
||||
#if _MSC_VER && __INTELLISENSE__ // Memory Layout view shows wrong layout without this workaround
|
||||
# define BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS [[msvc::no_unique_address, no_unique_address]]
|
||||
|
||||
#elif _MSC_VER // normal MSVC
|
||||
# define BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
|
||||
|
||||
#else // other compilers
|
||||
# define BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS [[no_unique_address]]
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_LIFETIMEBOUND
|
||||
# if defined(__clang__)
|
||||
# define BOOST_SPIRIT_X3_LIFETIMEBOUND [[clang::lifetimebound]]
|
||||
# elif defined(_MSC_VER)
|
||||
# define BOOST_SPIRIT_X3_LIFETIMEBOUND [[msvc::lifetimebound]]
|
||||
# else
|
||||
# define BOOST_SPIRIT_X3_LIFETIMEBOUND
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2009 Hartmut Kaiser
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
Copyright (c) 2009 Hartmut Kaiser
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -54,7 +55,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
};
|
||||
|
||||
template <typename T, typename Encoding, typename BoolPolicies = bool_policies<T>>
|
||||
struct literal_bool_parser : parser<bool_parser<T, Encoding, BoolPolicies>>
|
||||
struct literal_bool_parser : parser<literal_bool_parser<T, Encoding, BoolPolicies>>
|
||||
{
|
||||
typedef Encoding encoding;
|
||||
typedef T attribute_type;
|
||||
@@ -114,7 +115,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
constexpr false_type false_ = { false };
|
||||
}
|
||||
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
typedef bool_parser<bool, char_encoding::standard_wide> bool_type;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2009 Hartmut Kaiser
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
Copyright (c) 2009 Hartmut Kaiser
|
||||
Copyright (c) 2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -11,19 +12,22 @@
|
||||
#include <boost/spirit/home/x3/string/detail/string_parse.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
#include <string_view>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default boolean policies
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T = bool>
|
||||
struct bool_policies
|
||||
{
|
||||
template <typename Iterator, typename Attribute, typename CaseCompare>
|
||||
static bool
|
||||
parse_true(Iterator& first, Iterator const& last, Attribute& attr_, CaseCompare const& case_compare)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename CaseCompare>
|
||||
[[nodiscard]] static constexpr bool
|
||||
parse_true(It& first, Se const& last, Attribute& attr_, CaseCompare const& case_compare)
|
||||
noexcept(std::is_nothrow_constructible_v<Attribute, T>)
|
||||
{
|
||||
if (detail::string_parse("true", first, last, unused, case_compare))
|
||||
using namespace std::string_view_literals;
|
||||
if (detail::string_parse("true"sv, first, last, unused, case_compare))
|
||||
{
|
||||
traits::move_to(T(true), attr_); // result is true
|
||||
return true;
|
||||
@@ -31,11 +35,13 @@ namespace boost { namespace spirit { namespace x3
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Attribute, typename CaseCompare>
|
||||
static bool
|
||||
parse_false(Iterator& first, Iterator const& last, Attribute& attr_, CaseCompare const& case_compare)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename CaseCompare>
|
||||
[[nodiscard]] static constexpr bool
|
||||
parse_false(It& first, Se const& last, Attribute& attr_, CaseCompare const& case_compare)
|
||||
noexcept(std::is_nothrow_constructible_v<Attribute, T>)
|
||||
{
|
||||
if (detail::string_parse("false", first, last, unused, case_compare))
|
||||
using namespace std::string_view_literals;
|
||||
if (detail::string_parse("false"sv, first, last, unused, case_compare))
|
||||
{
|
||||
traits::move_to(T(false), attr_); // result is false
|
||||
return true;
|
||||
@@ -43,6 +49,6 @@ namespace boost { namespace spirit { namespace x3
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -11,11 +12,11 @@
|
||||
#include <boost/spirit/home/x3/string/detail/string_parse.hpp>
|
||||
#include <boost/spirit/home/x3/support/numeric_utils/extract_int.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
#include <string_view>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default (unsigned) real number policies
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default (unsigned) real number policies
|
||||
template <typename T>
|
||||
struct ureal_policies
|
||||
{
|
||||
@@ -72,24 +73,24 @@ namespace boost { namespace spirit { namespace x3
|
||||
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 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 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).
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// 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 Attribute>
|
||||
static bool
|
||||
parse_nan(Iterator& first, Iterator const& last, Attribute& attr_)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
if (first == last)
|
||||
return false; // end of input reached
|
||||
|
||||
@@ -97,7 +98,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
return false; // not "nan"
|
||||
|
||||
// nan[(...)] ?
|
||||
if (detail::string_parse("nan", "NAN", first, last, unused))
|
||||
if (detail::string_parse("nan"sv, "NAN"sv, first, last, unused))
|
||||
{
|
||||
if (first != last && *first == '(')
|
||||
{
|
||||
@@ -121,6 +122,8 @@ namespace boost { namespace spirit { namespace x3
|
||||
static bool
|
||||
parse_inf(Iterator& first, Iterator const& last, Attribute& attr_)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
if (first == last)
|
||||
return false; // end of input reached
|
||||
|
||||
@@ -128,10 +131,10 @@ namespace boost { namespace spirit { namespace x3
|
||||
return false; // not "inf"
|
||||
|
||||
// inf or infinity ?
|
||||
if (detail::string_parse("inf", "INF", first, last, unused))
|
||||
if (detail::string_parse("inf"sv, "INF"sv, first, last, unused))
|
||||
{
|
||||
// skip allowed 'inity' part of infinity
|
||||
detail::string_parse("inity", "INITY", first, last, unused);
|
||||
(void)detail::string_parse("inity"sv, "INITY"sv, first, last, unused);
|
||||
attr_ = std::numeric_limits<T>::infinity();
|
||||
return true;
|
||||
}
|
||||
@@ -139,9 +142,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default (signed) real number policies
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default (signed) real number policies
|
||||
template <typename T>
|
||||
struct real_policies : ureal_policies<T>
|
||||
{
|
||||
@@ -164,6 +165,6 @@ namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
static bool const expect_dot = true;
|
||||
};
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -8,6 +9,7 @@
|
||||
#define BOOST_SPIRIT_X3_STRING_FEBRUARY_03_2007_0355PM
|
||||
|
||||
#include <boost/spirit/home/x3/string/literal_string.hpp>
|
||||
#include <boost/spirit/home/x3/string/string.hpp>
|
||||
#include <boost/spirit/home/x3/string/symbols.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -9,36 +10,22 @@
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
#include <string_view>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
{
|
||||
template <typename Char, typename Iterator, typename Attribute, typename CaseCompareFunc>
|
||||
inline bool string_parse(
|
||||
Char const* str
|
||||
, Iterator& first, Iterator const& last, Attribute& attr, CaseCompareFunc const& compare)
|
||||
template <typename CharT, typename CharTraitsT, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename CaseCompareFunc>
|
||||
[[nodiscard]] constexpr bool
|
||||
string_parse(
|
||||
std::basic_string_view<CharT, CharTraitsT> const str,
|
||||
It& first, Se const& last,
|
||||
Attribute& attr, CaseCompareFunc const& compare
|
||||
) noexcept(std::is_same_v<std::remove_const_t<Attribute>, unused_type>)
|
||||
{
|
||||
Iterator i = first;
|
||||
Char ch = *str;
|
||||
|
||||
for (; !!ch; ++i)
|
||||
{
|
||||
if (i == last || (compare(ch, *i) != 0))
|
||||
return false;
|
||||
ch = *++str;
|
||||
}
|
||||
|
||||
x3::traits::move_to(first, i, attr);
|
||||
first = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename String, typename Iterator, typename Attribute, typename CaseCompareFunc>
|
||||
inline bool string_parse(
|
||||
String const& str
|
||||
, Iterator& first, Iterator const& last, Attribute& attr, CaseCompareFunc const& compare)
|
||||
{
|
||||
Iterator i = first;
|
||||
typename String::const_iterator stri = str.begin();
|
||||
typename String::const_iterator str_last = str.end();
|
||||
It i = first;
|
||||
auto stri = str.begin();
|
||||
auto str_last = str.end();
|
||||
|
||||
for (; stri != str_last; ++stri, ++i)
|
||||
if (i == last || (compare(*stri, *i) != 0))
|
||||
@@ -48,30 +35,29 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Char, typename Iterator, typename Attribute>
|
||||
inline bool string_parse(
|
||||
Char const* uc_i, Char const* lc_i
|
||||
, Iterator& first, Iterator const& last, Attribute& attr)
|
||||
template <typename CharT, typename CharTraitsT, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename CaseCompareFunc>
|
||||
[[nodiscard]] constexpr bool
|
||||
string_parse(
|
||||
std::basic_string<CharT, CharTraitsT> const& str,
|
||||
It& first, Se const& last,
|
||||
Attribute& attr, CaseCompareFunc const& compare
|
||||
) noexcept(std::is_same_v<std::remove_const_t<Attribute>, unused_type>)
|
||||
{
|
||||
Iterator i = first;
|
||||
|
||||
for (; *uc_i && *lc_i; ++uc_i, ++lc_i, ++i)
|
||||
if (i == last || ((*uc_i != *i) && (*lc_i != *i)))
|
||||
return false;
|
||||
x3::traits::move_to(first, i, attr);
|
||||
first = i;
|
||||
return true;
|
||||
return detail::string_parse(std::basic_string_view{str}, first, last, attr, compare);
|
||||
}
|
||||
|
||||
template <typename String, typename Iterator, typename Attribute>
|
||||
inline bool string_parse(
|
||||
String const& ucstr, String const& lcstr
|
||||
, Iterator& first, Iterator const& last, Attribute& attr)
|
||||
template <typename CharT, typename CharTraitsT, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
string_parse(
|
||||
std::basic_string_view<CharT, CharTraitsT> const ucstr,
|
||||
std::basic_string_view<CharT, CharTraitsT> const lcstr,
|
||||
It& first, Se const& last, Attribute& attr
|
||||
) noexcept(std::is_same_v<std::remove_const_t<Attribute>, unused_type>)
|
||||
{
|
||||
typename String::const_iterator uc_i = ucstr.begin();
|
||||
typename String::const_iterator uc_last = ucstr.end();
|
||||
typename String::const_iterator lc_i = lcstr.begin();
|
||||
Iterator i = first;
|
||||
auto uc_i = ucstr.begin();
|
||||
auto uc_last = ucstr.end();
|
||||
auto lc_i = lcstr.begin();
|
||||
It i = first;
|
||||
|
||||
for (; uc_i != uc_last; ++uc_i, ++lc_i, ++i)
|
||||
if (i == last || ((*uc_i != *i) && (*lc_i != *i)))
|
||||
@@ -80,6 +66,17 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
first = i;
|
||||
return true;
|
||||
}
|
||||
}}}}
|
||||
|
||||
template <typename CharT, typename CharTraitsT, std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
string_parse(
|
||||
std::basic_string<CharT, CharTraitsT> const& ucstr,
|
||||
std::basic_string<CharT, CharTraitsT> const& lcstr,
|
||||
It& first, Se const& last, Attribute& attr
|
||||
) noexcept(std::is_same_v<std::remove_const_t<Attribute>, unused_type>)
|
||||
{
|
||||
return detail::string_parse(std::basic_string_view{ucstr}, std::basic_string_view{lcstr}, first, last, attr);
|
||||
}
|
||||
} // boost::spirit::x3::detail
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
|
||||
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)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM)
|
||||
#define BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM
|
||||
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
// This file contains low level TST routines, not for
|
||||
// public consumption.
|
||||
|
||||
template <typename Char, typename T>
|
||||
struct tst_node
|
||||
{
|
||||
tst_node(Char id)
|
||||
: id(id), data(0), lt(0), eq(0), gt(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
static void
|
||||
destruct_node(tst_node* p, Alloc* alloc)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
if (p->data)
|
||||
alloc->delete_data(p->data);
|
||||
destruct_node(p->lt, alloc);
|
||||
destruct_node(p->eq, alloc);
|
||||
destruct_node(p->gt, alloc);
|
||||
alloc->delete_node(p);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
static tst_node*
|
||||
clone_node(tst_node* p, Alloc* alloc)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
tst_node* clone = alloc->new_node(p->id);
|
||||
if (p->data)
|
||||
clone->data = alloc->new_data(*p->data);
|
||||
clone->lt = clone_node(p->lt, alloc);
|
||||
clone->eq = clone_node(p->eq, alloc);
|
||||
clone->gt = clone_node(p->gt, alloc);
|
||||
return clone;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename CaseCompare>
|
||||
static T*
|
||||
find(tst_node* start, Iterator& first, Iterator last, CaseCompare comp)
|
||||
{
|
||||
if (first == last)
|
||||
return 0;
|
||||
|
||||
Iterator i = first;
|
||||
Iterator latest = first;
|
||||
tst_node* p = start;
|
||||
T* found = 0;
|
||||
|
||||
while (p && i != last)
|
||||
{
|
||||
int32_t c = comp(*i,p->id);
|
||||
if (c == 0)
|
||||
{
|
||||
if (p->data)
|
||||
{
|
||||
found = p->data;
|
||||
latest = i;
|
||||
}
|
||||
p = p->eq;
|
||||
i++;
|
||||
}
|
||||
else if (c < 0)
|
||||
{
|
||||
p = p->lt;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = p->gt;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
first = ++latest; // one past the last matching char
|
||||
return found;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Alloc>
|
||||
static T*
|
||||
add(
|
||||
tst_node*& start
|
||||
, Iterator first
|
||||
, Iterator last
|
||||
, typename boost::call_traits<T>::param_type val
|
||||
, Alloc* alloc)
|
||||
{
|
||||
if (first == last)
|
||||
return 0;
|
||||
|
||||
tst_node** pp = &start;
|
||||
for (;;)
|
||||
{
|
||||
auto c = *first;
|
||||
|
||||
if (*pp == 0)
|
||||
*pp = alloc->new_node(c);
|
||||
tst_node* p = *pp;
|
||||
|
||||
if (c == p->id)
|
||||
{
|
||||
if (++first == last)
|
||||
{
|
||||
if (p->data == 0)
|
||||
p->data = alloc->new_data(val);
|
||||
return p->data;
|
||||
}
|
||||
pp = &p->eq;
|
||||
}
|
||||
else if (c < p->id)
|
||||
{
|
||||
pp = &p->lt;
|
||||
}
|
||||
else
|
||||
{
|
||||
pp = &p->gt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Alloc>
|
||||
static void
|
||||
remove(tst_node*& p, Iterator first, Iterator last, Alloc* alloc)
|
||||
{
|
||||
if (p == 0 || first == last)
|
||||
return;
|
||||
|
||||
auto c = *first;
|
||||
|
||||
if (c == p->id)
|
||||
{
|
||||
if (++first == last)
|
||||
{
|
||||
if (p->data)
|
||||
{
|
||||
alloc->delete_data(p->data);
|
||||
p->data = 0;
|
||||
}
|
||||
}
|
||||
remove(p->eq, first, last, alloc);
|
||||
}
|
||||
else if (c < p->id)
|
||||
{
|
||||
remove(p->lt, first, last, alloc);
|
||||
}
|
||||
else
|
||||
{
|
||||
remove(p->gt, first, last, alloc);
|
||||
}
|
||||
|
||||
if (p->data == 0 && p->lt == 0 && p->eq == 0 && p->gt == 0)
|
||||
{
|
||||
alloc->delete_node(p);
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static void
|
||||
for_each(tst_node* p, std::basic_string<Char> prefix, F f)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
for_each(p->lt, prefix, f);
|
||||
std::basic_string<Char> s = prefix + p->id;
|
||||
for_each(p->eq, s, f);
|
||||
if (p->data)
|
||||
f(s, *p->data);
|
||||
for_each(p->gt, prefix, f);
|
||||
}
|
||||
}
|
||||
|
||||
Char id; // the node's identity character
|
||||
T* data; // optional data
|
||||
tst_node* lt; // left pointer
|
||||
tst_node* eq; // middle pointer
|
||||
tst_node* gt; // right pointer
|
||||
};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
175
include/boost/spirit/home/x3/string/detail/tst_node.hpp
Normal file
175
include/boost/spirit/home/x3/string/detail/tst_node.hpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM)
|
||||
#define BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM
|
||||
|
||||
#include <boost/spirit/home/x3/core/config.hpp>
|
||||
#include <boost/spirit/home/x3/support/allocator.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
{
|
||||
// This file contains low level TST routines, not for
|
||||
// public consumption.
|
||||
|
||||
template <typename Char, typename T, typename Alloc = std::allocator<T>>
|
||||
struct tst_node
|
||||
{
|
||||
using allocator_type = Alloc;
|
||||
using node_allocator_type = std::allocator_traits<Alloc>::template rebind_alloc<tst_node>;
|
||||
|
||||
constexpr explicit tst_node(Char id, Alloc const& alloc = {}) noexcept
|
||||
: alloc(alloc)
|
||||
, node_alloc(this->alloc)
|
||||
, id(id)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr tst_node(tst_node const& rhs)
|
||||
: alloc(std::allocator_traits<Alloc>::select_on_container_copy_construction(rhs.alloc))
|
||||
, node_alloc(std::allocator_traits<node_allocator_type>::select_on_container_copy_construction(rhs.node_alloc))
|
||||
, id(rhs.id)
|
||||
, data(allocator_ops<tst_node>::template copy_construct<&tst_node::alloc, &tst_node::data>(*this, rhs))
|
||||
, lt(allocator_ops<tst_node>::template copy_construct<&tst_node::node_alloc, &tst_node::lt>(*this, rhs))
|
||||
, eq(allocator_ops<tst_node>::template copy_construct<&tst_node::node_alloc, &tst_node::eq>(*this, rhs))
|
||||
, gt(allocator_ops<tst_node>::template copy_construct<&tst_node::node_alloc, &tst_node::gt>(*this, rhs))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr tst_node(tst_node&& rhs) noexcept
|
||||
: alloc(std::move(rhs.alloc))
|
||||
, node_alloc(std::move(rhs.node_alloc))
|
||||
, id(std::move(rhs.id))
|
||||
, data(std::exchange(rhs.data, nullptr))
|
||||
, lt(std::exchange(rhs.lt, nullptr))
|
||||
, eq(std::exchange(rhs.eq, nullptr))
|
||||
, gt(std::exchange(rhs.gt, nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr ~tst_node() noexcept
|
||||
{
|
||||
allocator_ops<tst_node>::template destroy_deallocate<
|
||||
&tst_node::alloc, &tst_node::data
|
||||
>(*this);
|
||||
|
||||
allocator_ops<tst_node>::template destroy_deallocate<
|
||||
&tst_node::node_alloc,
|
||||
&tst_node::lt, &tst_node::eq, &tst_node::gt
|
||||
>(*this);
|
||||
}
|
||||
|
||||
constexpr tst_node& operator=(tst_node const& rhs)
|
||||
{
|
||||
if (std::addressof(rhs) == this) return *this;
|
||||
|
||||
id = rhs.id;
|
||||
|
||||
allocator_ops<tst_node>::template copy_assign<
|
||||
&tst_node::alloc, &tst_node::data
|
||||
>(*this, rhs);
|
||||
|
||||
allocator_ops<tst_node>::template copy_assign<
|
||||
&tst_node::node_alloc,
|
||||
&tst_node::lt, &tst_node::eq, &tst_node::gt
|
||||
>(*this, rhs);
|
||||
}
|
||||
|
||||
constexpr tst_node& operator=(tst_node&& rhs)
|
||||
noexcept(allocator_ops<tst_node>::template move_assign_noexcept<allocator_type, node_allocator_type>)
|
||||
{
|
||||
if (std::addressof(rhs) == this) return *this;
|
||||
|
||||
id = std::move(rhs.id);
|
||||
|
||||
allocator_ops<tst_node>::template move_assign<
|
||||
&tst_node::alloc, &tst_node::data
|
||||
>(*this, std::move(rhs));
|
||||
|
||||
allocator_ops<tst_node>::template move_assign<
|
||||
&tst_node::node_alloc,
|
||||
&tst_node::lt, &tst_node::eq, &tst_node::gt
|
||||
>(*this, std::move(rhs));
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator, typename CaseCompare>
|
||||
[[nodiscard]] static constexpr T*
|
||||
find(tst_node* start, Iterator& first, Iterator last, CaseCompare const& comp) noexcept
|
||||
{
|
||||
if (first == last) return nullptr;
|
||||
|
||||
Iterator i = first;
|
||||
Iterator latest = first;
|
||||
tst_node* p = start;
|
||||
T* found = nullptr;
|
||||
|
||||
while (p && i != last)
|
||||
{
|
||||
auto c = comp(*i,p->id);
|
||||
if (c == 0) {
|
||||
if (p->data)
|
||||
{
|
||||
found = p->data;
|
||||
latest = i;
|
||||
}
|
||||
p = p->eq;
|
||||
++i;
|
||||
}
|
||||
else if (c < 0)
|
||||
{
|
||||
p = p->lt;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = p->gt;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
first = ++latest; // one past the last matching char
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static void
|
||||
for_each(tst_node* const p, std::basic_string_view<Char> const prefix, F&& f)
|
||||
{
|
||||
if (!p) return;
|
||||
|
||||
tst_node::for_each(p->lt, prefix, f);
|
||||
std::basic_string<Char> s = std::basic_string<Char>(prefix) + p->id;
|
||||
tst_node::for_each(p->eq, s, f);
|
||||
if (p->data)
|
||||
{
|
||||
f(s, *p->data);
|
||||
}
|
||||
tst_node::for_each(p->gt, prefix, f);
|
||||
}
|
||||
|
||||
friend struct allocator_ops<tst_node>;
|
||||
|
||||
BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS Alloc alloc;
|
||||
BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS node_allocator_type node_alloc;
|
||||
Char id; // the node's identity character
|
||||
T* data = nullptr; // optional data
|
||||
tst_node* lt = nullptr; // left pointer
|
||||
tst_node* eq = nullptr; // middle pointer
|
||||
tst_node* gt = nullptr; // right pointer
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -7,276 +8,66 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_LITERAL_STRING_APR_18_2006_1125PM)
|
||||
#define BOOST_SPIRIT_X3_LITERAL_STRING_APR_18_2006_1125PM
|
||||
|
||||
#include <boost/spirit/home/x3/string/detail/string_parse.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/skip_over.hpp>
|
||||
#include <boost/spirit/home/x3/string/detail/string_parse.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/support/no_case.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/utf8.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
template <typename String, typename Encoding,
|
||||
typename Attribute = std::basic_string<typename Encoding::char_type>>
|
||||
template <typename String, typename Encoding, typename Attribute = std::basic_string<typename Encoding::char_type>>
|
||||
struct literal_string : parser<literal_string<String, Encoding, Attribute>>
|
||||
{
|
||||
typedef typename Encoding::char_type char_type;
|
||||
typedef Encoding encoding;
|
||||
typedef Attribute attribute_type;
|
||||
static bool const has_attribute =
|
||||
!is_same<unused_type, attribute_type>::value;
|
||||
static bool const handles_container = has_attribute;
|
||||
static_assert(
|
||||
!std::is_pointer_v<std::decay_t<String>>,
|
||||
"`literal_string` for raw character pointer/array is banned; it has an undetectable risk of holding a dangling pointer."
|
||||
);
|
||||
static_assert(std::is_convertible_v<String, std::basic_string_view<typename String::value_type>>);
|
||||
|
||||
constexpr literal_string(typename add_reference< typename add_const<String>::type >::type str)
|
||||
: str(str)
|
||||
using char_type = typename Encoding::char_type;
|
||||
using encoding = Encoding;
|
||||
using attribute_type = Attribute;
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
static constexpr bool handles_container = has_attribute;
|
||||
|
||||
template<class... Args>
|
||||
requires std::is_constructible_v<String, Args...>
|
||||
constexpr literal_string(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible_v<String, Args...>)
|
||||
: str(std::forward<Args>(args)...)
|
||||
{}
|
||||
|
||||
template <typename Iterator, typename Context, typename Attribute_>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, unused_type, Attribute_& attr) const
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
Iterator& first, Iterator const& last,
|
||||
Context const& context, unused_type, Attribute_& attr
|
||||
) const
|
||||
{
|
||||
x3::skip_over(first, last, context);
|
||||
return detail::string_parse(str, first, last, attr, get_case_compare<encoding>(context));
|
||||
return detail::string_parse(str, first, last, attr, x3::get_case_compare<encoding>(context));
|
||||
}
|
||||
|
||||
String str;
|
||||
};
|
||||
|
||||
namespace standard
|
||||
{
|
||||
constexpr literal_string<char const*, char_encoding::standard>
|
||||
string(char const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<char>, char_encoding::standard>
|
||||
string(std::basic_string<char> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline constexpr literal_string<char const*, char_encoding::standard, unused_type>
|
||||
lit(char const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
literal_string<std::basic_string<Char>, char_encoding::standard, unused_type>
|
||||
lit(std::basic_string<Char> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
constexpr literal_string<wchar_t const*, char_encoding::standard_wide>
|
||||
string(wchar_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<wchar_t>, char_encoding::standard_wide>
|
||||
string(std::basic_string<wchar_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
constexpr literal_string<wchar_t const*, char_encoding::standard_wide, unused_type>
|
||||
lit(wchar_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<wchar_t>, char_encoding::standard_wide, unused_type>
|
||||
lit(std::basic_string<wchar_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_SPIRIT_X3_UNICODE)
|
||||
namespace unicode
|
||||
{
|
||||
constexpr literal_string<char32_t const*, char_encoding::unicode>
|
||||
string(char32_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<char32_t>, char_encoding::unicode>
|
||||
string(std::basic_string<char32_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
constexpr literal_string<char32_t const*, char_encoding::unicode, unused_type>
|
||||
lit(char32_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<char32_t>, char_encoding::unicode, unused_type>
|
||||
lit(std::basic_string<char32_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace ascii
|
||||
{
|
||||
constexpr literal_string<wchar_t const*, char_encoding::ascii>
|
||||
string(wchar_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<wchar_t>, char_encoding::ascii>
|
||||
string(std::basic_string<wchar_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
constexpr literal_string<char const*, char_encoding::ascii, unused_type>
|
||||
lit(char const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
literal_string<std::basic_string<Char>, char_encoding::ascii, unused_type>
|
||||
lit(std::basic_string<Char> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
|
||||
namespace iso8859_1
|
||||
{
|
||||
constexpr literal_string<wchar_t const*, char_encoding::iso8859_1>
|
||||
string(wchar_t const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
inline literal_string<std::basic_string<wchar_t>, char_encoding::iso8859_1>
|
||||
string(std::basic_string<wchar_t> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
constexpr literal_string<char const*, char_encoding::iso8859_1, unused_type>
|
||||
lit(char const* s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
literal_string<std::basic_string<Char>, char_encoding::iso8859_1, unused_type>
|
||||
lit(std::basic_string<Char> const& s)
|
||||
{
|
||||
return { s };
|
||||
}
|
||||
}
|
||||
|
||||
using standard::string;
|
||||
using standard::lit;
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
using standard_wide::string;
|
||||
using standard_wide::lit;
|
||||
#endif
|
||||
|
||||
namespace extension
|
||||
{
|
||||
template <int N>
|
||||
struct as_parser<char[N]>
|
||||
{
|
||||
typedef literal_string<
|
||||
char const*, char_encoding::standard, unused_type>
|
||||
type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(char const* s)
|
||||
{
|
||||
return type(s);
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct as_parser<char const[N]> : as_parser<char[N]> {};
|
||||
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
template <int N>
|
||||
struct as_parser<wchar_t[N]>
|
||||
{
|
||||
typedef literal_string<
|
||||
wchar_t const*, char_encoding::standard_wide, unused_type>
|
||||
type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(wchar_t const* s)
|
||||
{
|
||||
return type(s);
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct as_parser<wchar_t const[N]> : as_parser<wchar_t[N]> {};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct as_parser<char const*>
|
||||
{
|
||||
typedef literal_string<
|
||||
char const*, char_encoding::standard, unused_type>
|
||||
type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static constexpr type call(char const* s)
|
||||
{
|
||||
return type(s);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
struct as_parser< std::basic_string<Char> >
|
||||
{
|
||||
typedef literal_string<
|
||||
Char const*, char_encoding::standard, unused_type>
|
||||
type;
|
||||
|
||||
typedef type value_type;
|
||||
|
||||
static type call(std::basic_string<Char> const& s)
|
||||
{
|
||||
return type(s.c_str());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename String, typename Encoding, typename Attribute>
|
||||
struct get_info<literal_string<String, Encoding, Attribute>>
|
||||
{
|
||||
typedef std::string result_type;
|
||||
std::string operator()(literal_string<String, Encoding, Attribute> const& p) const
|
||||
using result_type = std::string;
|
||||
[[nodiscard]] constexpr std::string operator()(literal_string<String, Encoding, Attribute> const& p) const
|
||||
{
|
||||
return '"' + to_utf8(p.str) + '"';
|
||||
return '"' + x3::to_utf8(p.str) + '"';
|
||||
}
|
||||
};
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
298
include/boost/spirit/home/x3/string/string.hpp
Normal file
298
include/boost/spirit/home/x3/string/string.hpp
Normal file
@@ -0,0 +1,298 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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_SPIRIT_X3_STRING_STRING_HPP
|
||||
#define BOOST_SPIRIT_X3_STRING_STRING_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/string/literal_string.hpp>
|
||||
#include <boost/spirit/home/x3/char/literal_char.hpp> // required for "c" -> 'c' optimization
|
||||
#include <boost/spirit/home/x3/support/traits/string_traits.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard_wide.hpp>
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
namespace standard
|
||||
{
|
||||
inline namespace helpers
|
||||
{
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::standard>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::standard>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard, std::basic_string<char>>
|
||||
string(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{"c"}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard, std::basic_string<char>>
|
||||
string(traits::X3VagueArrayOf2Chars<char> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::standard, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::standard, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
} // helpers
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, char> || traits::StringLikeIncompatibleWith<T, char>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
} // standard
|
||||
|
||||
using standard::helpers::string;
|
||||
using standard::helpers::lit;
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
inline namespace helpers
|
||||
{
|
||||
template <traits::CppStringLike<wchar_t> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::standard_wide>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::standard_wide>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard_wide, std::basic_string<wchar_t>>
|
||||
string(wchar_t ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{L"c"}` into `literal_char{L'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::standard_wide, std::basic_string<wchar_t>>
|
||||
string(traits::X3VagueArrayOf2Chars<wchar_t> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<wchar_t> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::standard_wide, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::standard_wide, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
} // helpers
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, wchar_t> || traits::StringLikeIncompatibleWith<T, wchar_t>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
} // standard_wide
|
||||
|
||||
using standard_wide::helpers::string;
|
||||
using standard_wide::helpers::lit;
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
namespace unicode
|
||||
{
|
||||
inline namespace helpers
|
||||
{
|
||||
// TODO: add `char8_t` and `char16_t` overloads
|
||||
template <traits::CppStringLike<char32_t> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::unicode>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::unicode>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::unicode, std::basic_string<char32_t>>
|
||||
string(char32_t ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{U"c"}` into `literal_char{U'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::unicode, std::basic_string<char32_t>>
|
||||
string(traits::X3VagueArrayOf2Chars<char32_t> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<char32_t> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::unicode, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::unicode, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
} // helpers
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, char32_t> || traits::StringLikeIncompatibleWith<T, char32_t>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
}
|
||||
|
||||
using unicode::helpers::string;
|
||||
using unicode::helpers::lit;
|
||||
#endif
|
||||
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] ascii
|
||||
{
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::ascii>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::ascii>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::ascii, std::basic_string<char>>
|
||||
string(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{"c"}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::ascii, std::basic_string<char>>
|
||||
string(traits::X3VagueArrayOf2Chars<char> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::ascii, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::ascii, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, char> || traits::StringLikeIncompatibleWith<T, char>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
} // ascii
|
||||
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] iso8859_1
|
||||
{
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::iso8859_1>
|
||||
string(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::iso8859_1>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
// Optimize `literal_string{'c'}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::iso8859_1, std::basic_string<char>>
|
||||
string(char ch) noexcept
|
||||
{
|
||||
return { ch };
|
||||
}
|
||||
|
||||
// Optimize `literal_string{"c"}` into `literal_char{'c'}`
|
||||
[[nodiscard]] constexpr literal_char<char_encoding::iso8859_1, std::basic_string<char>>
|
||||
string(traits::X3VagueArrayOf2Chars<char> auto const& ch) noexcept
|
||||
{
|
||||
return { ch[0] };
|
||||
}
|
||||
|
||||
template <traits::CppStringLike<char> T>
|
||||
[[nodiscard]] constexpr literal_string<traits::maybe_owning_string<T>, char_encoding::iso8859_1, unused_type>
|
||||
lit(T&& string_like)
|
||||
noexcept(std::is_nothrow_constructible_v<literal_string<traits::maybe_owning_string<T>, char_encoding::iso8859_1, unused_type>, T>)
|
||||
{
|
||||
return {std::forward<T>(string_like)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires traits::CharIncompatibleWith<T, char> || traits::StringLikeIncompatibleWith<T, char>
|
||||
constexpr void string(T&&) = delete; // Mixing incompatible character types is not allowed
|
||||
} // iso8859_1
|
||||
|
||||
namespace extension
|
||||
{
|
||||
template <traits::CharLike CharT, std::size_t N>
|
||||
struct as_parser<CharT[N]>
|
||||
{
|
||||
using type = literal_string<std::basic_string_view<CharT>, traits::char_encoding_for<CharT>, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
[[nodiscard]] static constexpr type call(CharT const* s)
|
||||
{
|
||||
return type(s);
|
||||
}
|
||||
};
|
||||
|
||||
template <traits::CharLike CharT, std::size_t N>
|
||||
struct as_parser<CharT const[N]> : as_parser<CharT[N]> {};
|
||||
|
||||
template <traits::CharLike CharT>
|
||||
struct as_parser<CharT const*>
|
||||
{
|
||||
using type = literal_string<std::basic_string_view<CharT>, traits::char_encoding_for<CharT>, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
[[nodiscard]] static constexpr type call(CharT const* s)
|
||||
{
|
||||
return type(std::basic_string_view<CharT>{s});
|
||||
}
|
||||
};
|
||||
|
||||
template <traits::CharLike CharT>
|
||||
struct as_parser<std::basic_string<CharT>>
|
||||
{
|
||||
using type = literal_string<std::basic_string<CharT>, traits::char_encoding_for<CharT>, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] static constexpr type call(T&& str)
|
||||
noexcept(std::is_nothrow_constructible_v<type, T>)
|
||||
{
|
||||
return type(std::forward<T>(str));
|
||||
}
|
||||
};
|
||||
|
||||
template <traits::CharLike CharT>
|
||||
struct as_parser<std::basic_string_view<CharT>>
|
||||
{
|
||||
using type = literal_string<std::basic_string_view<CharT>, traits::char_encoding_for<CharT>, unused_type>;
|
||||
using value_type = type;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] static constexpr type call(T&& str)
|
||||
noexcept(std::is_nothrow_constructible_v<type, T>)
|
||||
{
|
||||
return type(std::forward<T>(str));
|
||||
}
|
||||
};
|
||||
} // extension
|
||||
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Carl Barron
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -16,99 +17,154 @@
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/support/no_case.hpp>
|
||||
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/detail/encoding_warning.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/iso8859_1.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard.hpp>
|
||||
#include <boost/spirit/home/x3/char_encoding/standard_wide.hpp>
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <ranges>
|
||||
#include <iterator>
|
||||
#include <initializer_list>
|
||||
#include <iterator> // std::begin
|
||||
#include <memory> // std::shared_ptr
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
#define BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING(old_api) \
|
||||
"Use `shared_" old_api "` instead. `" old_api "` has had a " \
|
||||
"*implicit* trait where the underlying storage is shared via " \
|
||||
"`std::shared_ptr`. This disallows `constexpr` usage in generic " \
|
||||
"scenarios where the sharing is not actually needed at all. Even " \
|
||||
"for non-`constexpr` usage, the old name `" old_api "` does not " \
|
||||
"represent this trait, so the usage of the old API is strongly " \
|
||||
"discouraged."
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
template <
|
||||
typename Encoding
|
||||
, typename T = unused_type
|
||||
, typename Lookup = tst<typename Encoding::char_type, T> >
|
||||
struct symbols_parser : parser<symbols_parser<Encoding, T, Lookup>>
|
||||
namespace detail
|
||||
{
|
||||
template <typename Derived, bool IsShared, typename Encoding, typename T, typename Lookup>
|
||||
struct symbols_parser_impl : parser<Derived>
|
||||
{
|
||||
typedef typename Encoding::char_type char_type; // the character type
|
||||
typedef Encoding encoding;
|
||||
typedef T value_type; // the value associated with each entry
|
||||
typedef value_type attribute_type;
|
||||
using char_type = typename Encoding::char_type; // the character type
|
||||
using encoding = Encoding;
|
||||
using value_type = T; // the value associated with each entry
|
||||
using attribute_type = value_type;
|
||||
|
||||
static bool const has_attribute =
|
||||
!std::is_same<unused_type, attribute_type>::value;
|
||||
static bool const handles_container =
|
||||
traits::is_container<attribute_type>::value;
|
||||
static constexpr bool has_attribute = !std::is_same_v<unused_type, attribute_type>;
|
||||
static constexpr bool handles_container = traits::is_container_v<attribute_type>;
|
||||
|
||||
symbols_parser(std::string const& name = "symbols")
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(std::make_shared<Lookup>())
|
||||
, name_(name)
|
||||
constexpr symbols_parser_impl(std::string_view name = "symbols")
|
||||
requires(IsShared)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(std::make_shared<Lookup>())
|
||||
, name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
symbols_parser(symbols_parser const& syms)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(syms.lookup)
|
||||
, name_(syms.name_)
|
||||
constexpr symbols_parser_impl(std::string_view name = "symbols")
|
||||
requires(!IsShared)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(std::make_unique<Lookup>())
|
||||
, name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Symbols>
|
||||
symbols_parser(Symbols const& syms, std::string const& name = "symbols")
|
||||
: symbols_parser(name)
|
||||
constexpr symbols_parser_impl(symbols_parser_impl const& syms)
|
||||
requires(IsShared)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(syms.lookup)
|
||||
, name_(syms.name_)
|
||||
{
|
||||
for (auto& sym : syms)
|
||||
add(sym);
|
||||
}
|
||||
|
||||
template <typename Symbols, typename Data>
|
||||
symbols_parser(Symbols const& syms, Data const& data
|
||||
, std::string const& name = "symbols")
|
||||
: symbols_parser(name)
|
||||
constexpr symbols_parser_impl(symbols_parser_impl const& syms)
|
||||
requires(!IsShared)
|
||||
: add{*this}
|
||||
, remove{*this}
|
||||
, lookup(std::make_unique<Lookup>(*syms.lookup))
|
||||
, name_(syms.name_)
|
||||
{
|
||||
using std::begin;
|
||||
auto di = begin(data);
|
||||
for (auto& sym : syms)
|
||||
add(sym, *di++);
|
||||
}
|
||||
|
||||
symbols_parser(std::initializer_list<std::pair<char_type const*, T>> syms
|
||||
, std::string const & name="symbols")
|
||||
: symbols_parser(name)
|
||||
constexpr symbols_parser_impl(symbols_parser_impl&&) noexcept = default;
|
||||
|
||||
template <std::ranges::forward_range Symbols>
|
||||
requires std::convertible_to<std::ranges::range_value_t<Symbols>, std::basic_string_view<char_type>>
|
||||
constexpr symbols_parser_impl(Symbols const& syms, std::string const& name = "symbols")
|
||||
: symbols_parser_impl(name)
|
||||
{
|
||||
for (auto& sym : syms)
|
||||
for (auto const& sym : syms)
|
||||
{
|
||||
this->add(sym);
|
||||
}
|
||||
}
|
||||
|
||||
template <std::ranges::forward_range Symbols, std::ranges::forward_range Data>
|
||||
requires
|
||||
std::convertible_to<std::ranges::range_value_t<Symbols>, std::basic_string_view<char_type>> &&
|
||||
std::convertible_to<std::ranges::range_value_t<Data>, T>
|
||||
constexpr symbols_parser_impl(
|
||||
Symbols const& syms, Data const& data, std::string const& name = "symbols"
|
||||
)
|
||||
: symbols_parser_impl(name)
|
||||
{
|
||||
auto di = std::ranges::begin(data);
|
||||
for (auto const& sym : syms)
|
||||
{
|
||||
this->add(sym, *di++);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr symbols_parser_impl(
|
||||
std::initializer_list<std::pair<char_type const*, T>> syms,
|
||||
std::string const & name="symbols"
|
||||
)
|
||||
: symbols_parser_impl(name)
|
||||
{
|
||||
for (auto const& sym : syms)
|
||||
{
|
||||
add(sym.first, sym.second);
|
||||
}
|
||||
}
|
||||
|
||||
symbols_parser(std::initializer_list<char_type const*> syms
|
||||
, std::string const &name="symbols")
|
||||
: symbols_parser(name)
|
||||
constexpr symbols_parser_impl(
|
||||
std::initializer_list<char_type const*> syms,
|
||||
std::string const &name="symbols"
|
||||
)
|
||||
: symbols_parser_impl(name)
|
||||
{
|
||||
for (auto str : syms)
|
||||
for (auto const& str : syms)
|
||||
{
|
||||
add(str);
|
||||
}
|
||||
}
|
||||
|
||||
symbols_parser&
|
||||
operator=(symbols_parser const& rhs)
|
||||
constexpr symbols_parser_impl& operator=(symbols_parser_impl const& rhs)
|
||||
{
|
||||
name_ = rhs.name_;
|
||||
lookup = rhs.lookup;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void clear()
|
||||
constexpr symbols_parser_impl& operator=(symbols_parser_impl&&) noexcept = default;
|
||||
|
||||
constexpr void clear() noexcept
|
||||
{
|
||||
lookup->clear();
|
||||
}
|
||||
@@ -116,93 +172,75 @@ namespace boost { namespace spirit { namespace x3
|
||||
struct adder;
|
||||
struct remover;
|
||||
|
||||
template <typename Str>
|
||||
adder const&
|
||||
operator=(Str const& str)
|
||||
constexpr adder const&
|
||||
operator=(std::basic_string_view<char_type> const s)
|
||||
{
|
||||
lookup->clear();
|
||||
return add(str);
|
||||
return this->add(s);
|
||||
}
|
||||
|
||||
template <typename Str>
|
||||
friend adder const&
|
||||
operator+=(symbols_parser& sym, Str const& str)
|
||||
friend constexpr adder const&
|
||||
operator+=(symbols_parser_impl& sym, std::basic_string_view<char_type> const s)
|
||||
{
|
||||
return sym.add(str);
|
||||
return sym.add(s);
|
||||
}
|
||||
|
||||
template <typename Str>
|
||||
friend remover const&
|
||||
operator-=(symbols_parser& sym, Str const& str)
|
||||
friend constexpr remover const&
|
||||
operator-=(symbols_parser_impl& sym, std::basic_string_view<char_type> const s)
|
||||
{
|
||||
return sym.remove(str);
|
||||
return sym.remove(s);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void for_each(F f) const
|
||||
constexpr void for_each(F&& f) const
|
||||
{
|
||||
lookup->for_each(f);
|
||||
lookup->for_each(std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename Str>
|
||||
value_type& at(Str const& str)
|
||||
template <typename F>
|
||||
constexpr void for_each(F&& f)
|
||||
{
|
||||
return *lookup->add(traits::get_string_begin<char_type>(str)
|
||||
, traits::get_string_end<char_type>(str), T());
|
||||
lookup->for_each(std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
value_type* prefix_find(Iterator& first, Iterator const& last)
|
||||
[[nodiscard]] constexpr value_type& at(std::basic_string_view<char_type> const s)
|
||||
{
|
||||
return *lookup->add(s.begin(), s.end(), T{});
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator>
|
||||
[[nodiscard]] constexpr value_type* prefix_find(Iterator& first, Iterator const& last) noexcept
|
||||
{
|
||||
return lookup->find(first, last, case_compare<Encoding>());
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
value_type const* prefix_find(Iterator& first, Iterator const& last) const
|
||||
template <std::forward_iterator Iterator>
|
||||
[[nodiscard]] constexpr value_type const* prefix_find(Iterator& first, Iterator const& last) const noexcept
|
||||
{
|
||||
return lookup->find(first, last, case_compare<Encoding>());
|
||||
}
|
||||
|
||||
template <typename Str>
|
||||
value_type* find(Str const& str)
|
||||
[[nodiscard]] constexpr value_type* find(std::basic_string_view<char_type> const s) noexcept
|
||||
{
|
||||
return find_impl(traits::get_string_begin<char_type>(str)
|
||||
, traits::get_string_end<char_type>(str));
|
||||
return this->find_impl(s.begin(), s.end());
|
||||
}
|
||||
|
||||
template <typename Str>
|
||||
value_type const* find(Str const& str) const
|
||||
[[nodiscard]] constexpr value_type const* find(std::basic_string_view<char_type> const s) const noexcept
|
||||
{
|
||||
return find_impl(traits::get_string_begin<char_type>(str)
|
||||
, traits::get_string_end<char_type>(str));
|
||||
return this->find_impl(s.begin(), s.end());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename Iterator>
|
||||
value_type* find_impl(Iterator begin, Iterator end)
|
||||
{
|
||||
value_type* r = lookup->find(begin, end, case_compare<Encoding>());
|
||||
return begin == end ? r : 0;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
value_type const* find_impl(Iterator begin, Iterator end) const
|
||||
{
|
||||
value_type const* r = lookup->find(begin, end, case_compare<Encoding>());
|
||||
return begin == end ? r : 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template <typename Iterator, typename Context, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, unused_type, Attribute& attr) const
|
||||
template <std::forward_iterator Iterator, typename Context, typename Attribute>
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
Iterator& first, Iterator const& last, Context const& context, unused_type, Attribute& attr
|
||||
) const noexcept(
|
||||
noexcept(x3::skip_over(first, last, context)) &&
|
||||
noexcept(x3::traits::move_to(std::declval<value_type const&>(), attr))
|
||||
)
|
||||
{
|
||||
x3::skip_over(first, last, context);
|
||||
|
||||
if (value_type const* val_ptr
|
||||
= lookup->find(first, last, get_case_compare<Encoding>(context)))
|
||||
if (value_type const* val_ptr = lookup->find(first, last, x3::get_case_compare<Encoding>(context)))
|
||||
{
|
||||
x3::traits::move_to(*val_ptr, attr);
|
||||
return true;
|
||||
@@ -210,124 +248,214 @@ namespace boost { namespace spirit { namespace x3
|
||||
return false;
|
||||
}
|
||||
|
||||
void name(std::string const &str)
|
||||
constexpr void name(std::string const &str)
|
||||
{
|
||||
name_ = str;
|
||||
}
|
||||
std::string const &name() const
|
||||
[[nodiscard]] constexpr std::string const& name() const noexcept
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
struct adder
|
||||
struct [[maybe_unused]] adder
|
||||
{
|
||||
template <typename Iterator>
|
||||
adder const&
|
||||
template <std::forward_iterator Iterator>
|
||||
[[maybe_unused]] constexpr adder const&
|
||||
operator()(Iterator first, Iterator last, T const& val) const
|
||||
{
|
||||
sym.lookup->add(first, last, val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Str>
|
||||
adder const&
|
||||
operator()(Str const& s, T const& val = T()) const
|
||||
[[maybe_unused]] constexpr adder const&
|
||||
operator()(std::basic_string_view<char_type> const s, T const& val = T{}) const
|
||||
{
|
||||
sym.lookup->add(traits::get_string_begin<char_type>(s)
|
||||
, traits::get_string_end<char_type>(s), val);
|
||||
sym.lookup->add(s.begin(), s.end(), val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Str>
|
||||
adder const&
|
||||
operator,(Str const& s) const
|
||||
[[maybe_unused, deprecated("Don't rely on overloaded comma operator. It's the leftover from the black magic in the 2000s.")]]
|
||||
constexpr adder const&
|
||||
operator,(std::basic_string_view<char_type> const s) const
|
||||
{
|
||||
sym.lookup->add(traits::get_string_begin<char_type>(s)
|
||||
, traits::get_string_end<char_type>(s), T());
|
||||
sym.lookup->add(s.begin(), s.end(), T{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
symbols_parser& sym;
|
||||
symbols_parser_impl& sym;
|
||||
};
|
||||
|
||||
struct remover
|
||||
struct [[maybe_unused]] remover
|
||||
{
|
||||
template <typename Iterator>
|
||||
remover const&
|
||||
template <std::forward_iterator Iterator>
|
||||
[[maybe_unused]] constexpr remover const&
|
||||
operator()(Iterator const& first, Iterator const& last) const
|
||||
{
|
||||
sym.lookup->remove(first, last);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Str>
|
||||
remover const&
|
||||
operator()(Str const& s) const
|
||||
[[maybe_unused]] constexpr remover const&
|
||||
operator()(std::basic_string_view<char_type> const s) const
|
||||
{
|
||||
sym.lookup->remove(traits::get_string_begin<char_type>(s)
|
||||
, traits::get_string_end<char_type>(s));
|
||||
sym.lookup->remove(s.begin(), s.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Str>
|
||||
remover const&
|
||||
operator,(Str const& s) const
|
||||
[[maybe_unused, deprecated("Don't rely on overloaded comma operator. It's the leftover from the black magic in the 2000s.")]]
|
||||
constexpr remover const&
|
||||
operator,(std::basic_string_view<char_type> const s) const
|
||||
{
|
||||
sym.lookup->remove(traits::get_string_begin<char_type>(s)
|
||||
, traits::get_string_end<char_type>(s));
|
||||
sym.lookup->remove(s.begin(), s.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
symbols_parser& sym;
|
||||
symbols_parser_impl& sym;
|
||||
};
|
||||
|
||||
adder add;
|
||||
remover remove;
|
||||
std::shared_ptr<Lookup> lookup;
|
||||
[[maybe_unused]] adder add;
|
||||
[[maybe_unused]] remover remove;
|
||||
|
||||
private:
|
||||
template <std::forward_iterator Iterator>
|
||||
[[nodiscard]] constexpr value_type* find_impl(Iterator begin, Iterator end) noexcept
|
||||
{
|
||||
value_type* r = lookup->find(begin, end, case_compare<Encoding>());
|
||||
return begin == end ? r : 0;
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator>
|
||||
[[nodiscard]] constexpr value_type const* find_impl(Iterator begin, Iterator end) const noexcept
|
||||
{
|
||||
value_type const* r = lookup->find(begin, end, case_compare<Encoding>());
|
||||
return begin == end ? r : 0;
|
||||
}
|
||||
|
||||
std::conditional_t<IsShared, std::shared_ptr<Lookup>, std::unique_ptr<Lookup>> lookup;
|
||||
std::string name_;
|
||||
};
|
||||
} // detail
|
||||
|
||||
template <typename Encoding, typename T = unused_type, typename Lookup = tst<typename Encoding::char_type, T>>
|
||||
struct shared_symbols_parser
|
||||
: detail::symbols_parser_impl<shared_symbols_parser<Encoding, T, Lookup>, true, Encoding, T, Lookup>
|
||||
{
|
||||
using base_type = detail::symbols_parser_impl<shared_symbols_parser<Encoding, T, Lookup>, true, Encoding, T, Lookup>;
|
||||
using base_type::base_type;
|
||||
using base_type::operator=;
|
||||
};
|
||||
|
||||
template <typename Encoding, typename T = unused_type, typename Lookup = tst<typename Encoding::char_type, T>>
|
||||
struct [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols_parser"))]]
|
||||
symbols_parser : shared_symbols_parser<Encoding, T, Lookup>
|
||||
{
|
||||
using base_type = shared_symbols_parser<Encoding, T, Lookup>;
|
||||
using base_type::base_type;
|
||||
using base_type::operator=;
|
||||
};
|
||||
|
||||
template <typename Encoding, typename T = unused_type, typename Lookup = tst<typename Encoding::char_type, T>>
|
||||
struct unique_symbols_parser
|
||||
: detail::symbols_parser_impl<unique_symbols_parser<Encoding, T, Lookup>, false, Encoding, T, Lookup>
|
||||
{
|
||||
using base_type = detail::symbols_parser_impl<unique_symbols_parser<Encoding, T, Lookup>, false, Encoding, T, Lookup>;
|
||||
using base_type::base_type;
|
||||
using base_type::operator=;
|
||||
};
|
||||
|
||||
template <typename Encoding, typename T, typename Lookup>
|
||||
struct get_info<symbols_parser<Encoding, T, Lookup>>
|
||||
struct get_info<shared_symbols_parser<Encoding, T, Lookup>>
|
||||
{
|
||||
typedef std::string result_type;
|
||||
result_type operator()(symbols_parser< Encoding, T
|
||||
, Lookup
|
||||
> const& symbols) const
|
||||
{
|
||||
return symbols.name();
|
||||
}
|
||||
using result_type = std::string const&;
|
||||
|
||||
[[nodiscard]] constexpr result_type operator()(shared_symbols_parser<Encoding, T, Lookup> const& symbols) const noexcept
|
||||
{
|
||||
return symbols.name();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Encoding, typename T, typename Lookup>
|
||||
struct get_info<unique_symbols_parser<Encoding, T, Lookup>>
|
||||
{
|
||||
using result_type = std::string const&;
|
||||
|
||||
[[nodiscard]] constexpr result_type operator()(unique_symbols_parser<Encoding, T, Lookup> const& symbols) const noexcept
|
||||
{
|
||||
return symbols.name();
|
||||
}
|
||||
};
|
||||
|
||||
namespace standard
|
||||
{
|
||||
template <typename T = unused_type>
|
||||
using symbols = symbols_parser<char_encoding::standard, T>;
|
||||
}
|
||||
using symbols [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols"))]]
|
||||
= x3::shared_symbols_parser<char_encoding::standard, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::standard, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::standard, T>;
|
||||
} // standard
|
||||
|
||||
using standard::symbols;
|
||||
using standard::shared_symbols;
|
||||
using standard::unique_symbols;
|
||||
|
||||
#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
namespace standard_wide
|
||||
{
|
||||
template <typename T = unused_type>
|
||||
using symbols = symbols_parser<char_encoding::standard_wide, T>;
|
||||
}
|
||||
using symbols [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols"))]]
|
||||
= x3::shared_symbols_parser<char_encoding::standard_wide, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::standard_wide, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::standard_wide, T>;
|
||||
} // standard_wide
|
||||
#endif
|
||||
|
||||
namespace ascii
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] ascii
|
||||
{
|
||||
template <typename T = unused_type>
|
||||
using symbols = symbols_parser<char_encoding::ascii, T>;
|
||||
}
|
||||
using symbols [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols"))]]
|
||||
= x3::shared_symbols_parser<char_encoding::ascii, T>;
|
||||
|
||||
namespace iso8859_1
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::ascii, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::ascii, T>;
|
||||
} // ascii
|
||||
|
||||
namespace [[deprecated(BOOST_SPIRIT_X3_WRONG_ENCODING_ASSUMPTION_WARNING)]] iso8859_1
|
||||
{
|
||||
template <typename T = unused_type>
|
||||
using symbols = symbols_parser<char_encoding::iso8859_1, T>;
|
||||
}
|
||||
using symbols [[deprecated(BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING("symbols"))]]
|
||||
= x3::shared_symbols_parser<char_encoding::iso8859_1, T>;
|
||||
|
||||
}}}
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::iso8859_1, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::iso8859_1, T>;
|
||||
} // iso8859_1
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
namespace unicode {
|
||||
template <typename T = unused_type>
|
||||
using shared_symbols = x3::shared_symbols_parser<char_encoding::unicode, T>;
|
||||
|
||||
template <typename T = unused_type>
|
||||
using unique_symbols = x3::unique_symbols_parser<char_encoding::unicode, T>;
|
||||
} // unicode
|
||||
#endif
|
||||
|
||||
} // boost::spirit::x3
|
||||
|
||||
#undef BOOST_SPIRIT_X3_IMPLICIT_SHARED_SYMBOLS_WARNING
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -7,129 +8,208 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_TST_JUNE_03_2007_1031AM)
|
||||
#define BOOST_SPIRIT_X3_TST_JUNE_03_2007_1031AM
|
||||
|
||||
#include <boost/spirit/home/x3/string/detail/tst.hpp>
|
||||
#include <boost/spirit/home/x3/core/config.hpp>
|
||||
#include <boost/spirit/home/x3/string/detail/tst_node.hpp>
|
||||
#include <boost/spirit/home/x3/support/allocator.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
struct tst_pass_through
|
||||
{
|
||||
template <typename Char>
|
||||
Char operator()(Char ch) const
|
||||
[[nodiscard]] constexpr Char operator()(Char ch) const noexcept
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename T>
|
||||
template <typename Char, typename T, typename Alloc = std::allocator<T>>
|
||||
struct tst
|
||||
{
|
||||
typedef Char char_type; // the character type
|
||||
typedef T value_type; // the value associated with each entry
|
||||
typedef detail::tst_node<Char, T> node;
|
||||
using char_type = Char; // the character type
|
||||
using value_type = T; // the value associated with each entry
|
||||
using allocator_type = Alloc;
|
||||
using node = detail::tst_node<Char, T>;
|
||||
using node_allocator_type = std::allocator_traits<Alloc>::template rebind_alloc<node>;
|
||||
|
||||
tst()
|
||||
: root(0)
|
||||
constexpr tst() noexcept(std::is_nothrow_default_constructible_v<Alloc>) = default;
|
||||
|
||||
constexpr explicit tst(Alloc const& alloc) noexcept
|
||||
: alloc_(alloc)
|
||||
, node_alloc_(alloc_)
|
||||
{}
|
||||
|
||||
constexpr ~tst() noexcept
|
||||
{
|
||||
detail::allocator_ops<tst>::template destroy_deallocate<&tst::node_alloc_, &tst::root_>(*this);
|
||||
}
|
||||
|
||||
constexpr tst(tst const& other)
|
||||
: alloc_(std::allocator_traits<Alloc>::select_on_container_copy_construction(other.alloc_))
|
||||
, node_alloc_(std::allocator_traits<node_allocator_type>::select_on_container_copy_construction(other.node_alloc_))
|
||||
, root_(detail::allocator_ops<tst>::template copy_construct<&tst::node_alloc_, &tst::root_>(*this, other))
|
||||
{
|
||||
}
|
||||
|
||||
~tst()
|
||||
constexpr tst(tst&& other) noexcept
|
||||
: alloc_(std::move(other.alloc_))
|
||||
, node_alloc_(std::move(other.node_alloc_))
|
||||
, root_(std::exchange(other.root_, nullptr))
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
tst(tst const& rhs)
|
||||
: root(0)
|
||||
constexpr tst& operator=(tst const& other)
|
||||
{
|
||||
copy(rhs);
|
||||
}
|
||||
|
||||
tst& operator=(tst const& rhs)
|
||||
{
|
||||
return assign(rhs);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename CaseCompare>
|
||||
T* find(Iterator& first, Iterator last, CaseCompare caseCompare) const
|
||||
{
|
||||
return node::find(root, first, last, caseCompare);
|
||||
}
|
||||
|
||||
/*template <typename Iterator>
|
||||
T* find(Iterator& first, Iterator last) const
|
||||
{
|
||||
return find(first, last, case_compare<tst_pass_through());
|
||||
}*/
|
||||
|
||||
template <typename Iterator>
|
||||
T* add(
|
||||
Iterator first
|
||||
, Iterator last
|
||||
, typename boost::call_traits<T>::param_type val)
|
||||
{
|
||||
return node::add(root, first, last, val, this);
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void remove(Iterator first, Iterator last)
|
||||
{
|
||||
node::remove(root, first, last, this);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
node::destruct_node(root, this);
|
||||
root = 0;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void for_each(F f) const
|
||||
{
|
||||
node::for_each(root, std::basic_string<Char>(), f);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend struct detail::tst_node<Char, T>;
|
||||
|
||||
void copy(tst const& rhs)
|
||||
{
|
||||
root = node::clone_node(rhs.root, this);
|
||||
}
|
||||
|
||||
tst& assign(tst const& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
clear();
|
||||
copy(rhs);
|
||||
}
|
||||
if (this == std::addressof(other)) return *this;
|
||||
detail::allocator_ops<tst>::template copy_assign<&tst::node_alloc_, &tst::root_>(*this, other);
|
||||
detail::allocator_ops<tst>::template copy_assign<&tst::alloc_>(*this, other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node* root;
|
||||
|
||||
node* new_node(Char id)
|
||||
constexpr tst& operator=(tst&& other)
|
||||
noexcept(detail::allocator_ops<tst>::template move_assign_noexcept<allocator_type, node_allocator_type>)
|
||||
{
|
||||
return new node(id);
|
||||
if (this == std::addressof(other)) return *this;
|
||||
detail::allocator_ops<tst>::template move_assign<&tst::node_alloc_, &tst::root_>(*this, std::move(other));
|
||||
detail::allocator_ops<tst>::template move_assign<&tst::alloc_>(*this, std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* new_data(typename boost::call_traits<T>::param_type val)
|
||||
template <std::forward_iterator Iterator, typename CaseCompare>
|
||||
[[nodiscard]] constexpr T* find(Iterator& first, Iterator last, CaseCompare caseCompare) const noexcept
|
||||
{
|
||||
return new T(val);
|
||||
return node::find(root_, first, last, caseCompare);
|
||||
}
|
||||
|
||||
void delete_node(node* p)
|
||||
template <std::forward_iterator Iterator, typename Val>
|
||||
constexpr T* add(Iterator first, Iterator last, Val&& val)
|
||||
{
|
||||
delete p;
|
||||
if (first == last) return nullptr;
|
||||
if (!root_)
|
||||
{
|
||||
root_ = std::allocator_traits<node_allocator_type>::allocate(node_alloc_, 1);
|
||||
std::allocator_traits<node_allocator_type>::construct(node_alloc_, root_, *first, alloc_);
|
||||
}
|
||||
|
||||
return this->add(root_, first, last, std::forward<Val>(val));
|
||||
}
|
||||
|
||||
void delete_data(T* p)
|
||||
template <std::forward_iterator Iterator>
|
||||
constexpr void remove(Iterator first, Iterator last) noexcept
|
||||
{
|
||||
delete p;
|
||||
this->remove(root_, first, last);
|
||||
}
|
||||
|
||||
constexpr void clear() noexcept
|
||||
{
|
||||
if (!root_) return;
|
||||
std::allocator_traits<node_allocator_type>::destroy(node_alloc_, root_);
|
||||
std::allocator_traits<node_allocator_type>::deallocate(node_alloc_, root_, 1);
|
||||
root_ = nullptr;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr void for_each(F&& f) const
|
||||
{
|
||||
node::for_each(root_, {}, std::forward<F>(f));
|
||||
}
|
||||
|
||||
friend struct detail::allocator_ops<tst>;
|
||||
|
||||
private:
|
||||
template <std::forward_iterator Iterator, typename Val>
|
||||
[[nodiscard]] constexpr T*
|
||||
add(node* root, Iterator first, Iterator last, Val&& val)
|
||||
{
|
||||
BOOST_ASSERT(root != nullptr);
|
||||
BOOST_ASSERT(first != last);
|
||||
|
||||
node** pp = &root;
|
||||
auto c = *first;
|
||||
|
||||
while (true)
|
||||
{
|
||||
node* const p = *pp;
|
||||
|
||||
if (c == p->id)
|
||||
{
|
||||
if (++first == last)
|
||||
{
|
||||
if (!p->data)
|
||||
{
|
||||
p->data = std::allocator_traits<Alloc>::allocate(alloc_, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc_, p->data, std::forward<Val>(val));
|
||||
}
|
||||
return p->data;
|
||||
}
|
||||
pp = &p->eq;
|
||||
c = *first;
|
||||
}
|
||||
else if (c < p->id)
|
||||
{
|
||||
pp = &p->lt;
|
||||
}
|
||||
else
|
||||
{
|
||||
pp = &p->gt;
|
||||
}
|
||||
|
||||
if (!*pp)
|
||||
{
|
||||
*pp = std::allocator_traits<node_allocator_type>::allocate(node_alloc_, 1);
|
||||
std::allocator_traits<node_allocator_type>::construct(node_alloc_, *pp, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <std::forward_iterator Iterator>
|
||||
constexpr void
|
||||
remove(node*& p, Iterator first, Iterator last) noexcept
|
||||
{
|
||||
if (!p || first == last) return;
|
||||
|
||||
auto c = *first;
|
||||
|
||||
if (c == p->id)
|
||||
{
|
||||
if (++first == last)
|
||||
{
|
||||
if (p->data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc_, p->data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc_, p->data, 1);
|
||||
p->data = nullptr;
|
||||
}
|
||||
}
|
||||
this->remove(p->eq, first, last);
|
||||
}
|
||||
else if (c < p->id)
|
||||
{
|
||||
this->remove(p->lt, first, last);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->remove(p->gt, first, last);
|
||||
}
|
||||
|
||||
if (!p->data && !p->lt && !p->eq && !p->gt)
|
||||
{
|
||||
std::allocator_traits<node_allocator_type>::destroy(node_alloc_, p);
|
||||
std::allocator_traits<node_allocator_type>::deallocate(node_alloc_, p, 1);
|
||||
p = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS Alloc alloc_;
|
||||
BOOST_SPIRIT_X3_NO_UNIQUE_ADDRESS node_allocator_type node_alloc_;
|
||||
node* root_ = nullptr;
|
||||
};
|
||||
}}}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -7,9 +8,10 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_TST_MAP_JUNE_03_2007_1143AM)
|
||||
#define BOOST_SPIRIT_X3_TST_MAP_JUNE_03_2007_1143AM
|
||||
|
||||
#include <boost/spirit/home/x3/string/detail/tst.hpp>
|
||||
#include <boost/spirit/home/x3/string/tst.hpp>
|
||||
#include <unordered_map>
|
||||
#include <boost/pool/object_pool.hpp>
|
||||
#include <boost/call_traits.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
|
||||
251
include/boost/spirit/home/x3/support/allocator.hpp
Normal file
251
include/boost/spirit/home/x3/support/allocator.hpp
Normal file
@@ -0,0 +1,251 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_SUPPORT_ALLOCATOR_HPP)
|
||||
#define BOOST_SPIRIT_X3_SUPPORT_ALLOCATOR_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::detail {
|
||||
|
||||
template <typename Klass>
|
||||
struct allocator_ops
|
||||
{
|
||||
template <typename... Allocs>
|
||||
static constexpr bool move_assign_noexcept = std::conjunction_v<
|
||||
std::disjunction<
|
||||
typename std::allocator_traits<Allocs>::propagate_on_container_move_assignment,
|
||||
typename std::allocator_traits<Allocs>::is_always_equal
|
||||
>...
|
||||
>;
|
||||
|
||||
template <auto AllocMem, auto Mem>
|
||||
[[nodiscard]] static constexpr auto copy_construct(Klass& self, Klass const& other)
|
||||
-> std::remove_reference_t<decltype(self.*Mem)>
|
||||
{
|
||||
if (!(other.*Mem)) return nullptr;
|
||||
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
auto& alloc = self.*AllocMem;
|
||||
auto* data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, *(other.*Mem));
|
||||
return data;
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto... Mems>
|
||||
static constexpr void destroy_deallocate(Klass& self) noexcept
|
||||
{
|
||||
static_assert(sizeof...(Mems) > 0);
|
||||
(allocator_ops::destroy_deallocate_impl<AllocMem, Mems>(self), ...);
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto... Mems>
|
||||
static constexpr void copy_assign(Klass& self, Klass const& other)
|
||||
{
|
||||
BOOST_ASSERT(std::addressof(self) != std::addressof(other));
|
||||
|
||||
(allocator_ops::copy_assign_impl<AllocMem, Mems>(self, other), ...);
|
||||
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
constexpr bool pocca = std::allocator_traits<Alloc>::propagate_on_container_copy_assignment::value;
|
||||
if constexpr (pocca)
|
||||
{
|
||||
self.*AllocMem = other.*AllocMem;
|
||||
}
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto... Mems>
|
||||
static constexpr void move_assign(Klass& self, Klass&& other)
|
||||
noexcept(move_assign_noexcept<decltype(self.*AllocMem)>)
|
||||
{
|
||||
BOOST_ASSERT(std::addressof(self) != std::addressof(other));
|
||||
|
||||
(allocator_ops::move_assign_impl<AllocMem, Mems>(self, std::move(other)), ...);
|
||||
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
constexpr bool pocca = std::allocator_traits<Alloc>::propagate_on_container_move_assignment::value;
|
||||
if constexpr (pocca)
|
||||
{
|
||||
self.*AllocMem = std::move(other.*AllocMem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
template <auto AllocMem, auto Mem>
|
||||
static constexpr void destroy_deallocate_impl(Klass& self) noexcept
|
||||
{
|
||||
auto& data = self.*Mem;
|
||||
if (!data) return;
|
||||
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
auto& alloc = self.*AllocMem;
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto Mem>
|
||||
static constexpr void copy_assign_impl(Klass& self, Klass const& other)
|
||||
{
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
constexpr bool pocca = std::allocator_traits<Alloc>::propagate_on_container_copy_assignment::value;
|
||||
|
||||
auto& data = self.*Mem;
|
||||
auto& alloc = self.*AllocMem;
|
||||
|
||||
auto const& other_data = other.*Mem;
|
||||
auto const& other_alloc = other.*AllocMem;
|
||||
|
||||
if (other_data)
|
||||
{
|
||||
if constexpr (std::allocator_traits<Alloc>::is_always_equal::value)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
*data = *other_data;
|
||||
return;
|
||||
}
|
||||
if constexpr (pocca)
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(other_alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(other_alloc, data, *other_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, *other_data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (alloc == other_alloc)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
*data = *other_data;
|
||||
return;
|
||||
}
|
||||
if constexpr (pocca)
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(other_alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(other_alloc, data, *other_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, *other_data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
data = nullptr;
|
||||
}
|
||||
if constexpr (pocca)
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(other_alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(other_alloc, data, *other_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, *other_data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else // !other_data
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
data = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
template <auto AllocMem, auto Mem>
|
||||
static constexpr void move_assign_impl(Klass& self, Klass&& other)
|
||||
noexcept(move_assign_noexcept<std::remove_reference_t<decltype(self.*AllocMem)>>)
|
||||
{
|
||||
using Alloc = std::remove_reference_t<decltype(self.*AllocMem)>;
|
||||
constexpr bool pocma = std::allocator_traits<Alloc>::propagate_on_container_move_assignment::value;
|
||||
|
||||
auto& data = self.*Mem;
|
||||
auto& alloc = self.*AllocMem;
|
||||
|
||||
auto& other_data = other.*Mem;
|
||||
auto& other_alloc = other.*AllocMem;
|
||||
|
||||
if (other_data)
|
||||
{
|
||||
if constexpr (std::allocator_traits<Alloc>::is_always_equal::value)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
}
|
||||
data = std::exchange(other_data, nullptr);
|
||||
return;
|
||||
}
|
||||
else if (alloc == other_alloc)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
}
|
||||
data = std::exchange(other_data, nullptr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
}
|
||||
if constexpr (pocma)
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(other_alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(other_alloc, data, std::move(*other_data));
|
||||
}
|
||||
else
|
||||
{
|
||||
data = std::allocator_traits<Alloc>::allocate(alloc, 1);
|
||||
std::allocator_traits<Alloc>::construct(alloc, data, std::move(*other_data));
|
||||
}
|
||||
|
||||
std::allocator_traits<Alloc>::destroy(other_alloc, other_data);
|
||||
std::allocator_traits<Alloc>::deallocate(other_alloc, other_data, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else // !other_data
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
std::allocator_traits<Alloc>::destroy(alloc, data);
|
||||
std::allocator_traits<Alloc>::deallocate(alloc, data, 1);
|
||||
data = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::detail
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -11,7 +12,9 @@
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/char/char_class_tags.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
struct no_case_tag {};
|
||||
|
||||
@@ -19,19 +22,20 @@ namespace boost { namespace spirit { namespace x3
|
||||
struct case_compare
|
||||
{
|
||||
template <typename Char, typename CharSet>
|
||||
bool in_set(Char ch, CharSet const& set)
|
||||
[[nodiscard]] constexpr bool in_set(Char ch, CharSet const& set) noexcept
|
||||
{
|
||||
static_assert(noexcept(set.test(ch)));
|
||||
return set.test(ch);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
int32_t operator()(Char lc, Char rc) const
|
||||
[[nodiscard]] constexpr std::int32_t operator()(Char lc, Char rc) const noexcept
|
||||
{
|
||||
return lc - rc;
|
||||
}
|
||||
|
||||
template <typename CharClassTag>
|
||||
CharClassTag get_char_class_tag(CharClassTag tag) const
|
||||
[[nodiscard]] constexpr CharClassTag get_char_class_tag(CharClassTag tag) const noexcept
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
@@ -41,17 +45,18 @@ namespace boost { namespace spirit { namespace x3
|
||||
struct no_case_compare
|
||||
{
|
||||
template <typename Char, typename CharSet>
|
||||
bool in_set(Char ch_, CharSet const& set)
|
||||
[[nodiscard]] bool in_set(Char ch_, CharSet const& set) noexcept // TODO: constexpr
|
||||
{
|
||||
using char_type = typename Encoding::classify_type;
|
||||
auto ch = char_type(ch_);
|
||||
static_assert(noexcept(set.test(ch)));
|
||||
return set.test(ch)
|
||||
|| set.test(Encoding::islower(ch)
|
||||
? Encoding::toupper(ch) : Encoding::tolower(ch));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
int32_t operator()(Char lc_, Char const rc_) const
|
||||
[[nodiscard]] std::int32_t operator()(Char lc_, Char const rc_) const noexcept // TODO: constexpr
|
||||
{
|
||||
using char_type = typename Encoding::classify_type;
|
||||
auto lc = char_type(lc_);
|
||||
@@ -61,43 +66,45 @@ namespace boost { namespace spirit { namespace x3
|
||||
}
|
||||
|
||||
template <typename CharClassTag>
|
||||
CharClassTag get_char_class_tag(CharClassTag tag) const
|
||||
[[nodiscard]] constexpr CharClassTag get_char_class_tag(CharClassTag tag) const noexcept
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
alpha_tag get_char_class_tag(lower_tag ) const
|
||||
[[nodiscard]] constexpr alpha_tag get_char_class_tag(lower_tag) const noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
alpha_tag get_char_class_tag(upper_tag ) const
|
||||
[[nodiscard]] constexpr alpha_tag get_char_class_tag(upper_tag) const noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Encoding>
|
||||
case_compare<Encoding> get_case_compare_impl(unused_type const&)
|
||||
namespace detail
|
||||
{
|
||||
return {};
|
||||
}
|
||||
template <typename Encoding>
|
||||
[[nodiscard]] constexpr case_compare<Encoding> get_case_compare_impl(unused_type const&) noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename Encoding>
|
||||
no_case_compare<Encoding> get_case_compare_impl(no_case_tag const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
template <typename Encoding>
|
||||
[[nodiscard]] constexpr no_case_compare<Encoding> get_case_compare_impl(no_case_tag const&) noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
} // detail
|
||||
|
||||
template <typename Encoding, typename Context>
|
||||
inline decltype(auto) get_case_compare(Context const& context)
|
||||
[[nodiscard]] constexpr decltype(auto) get_case_compare(Context const& context) noexcept
|
||||
{
|
||||
return get_case_compare_impl<Encoding>(x3::get<no_case_tag>(context));
|
||||
return detail::get_case_compare_impl<Encoding>(x3::get<no_case_tag>(context));
|
||||
}
|
||||
|
||||
auto const no_case_compare_ = no_case_tag{};
|
||||
auto const no_case_compare_ = no_case_tag{}; // TODO: this should be private
|
||||
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_type.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/numeric_traits.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/ascii.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/char_encoding_traits.hpp>
|
||||
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
#include <boost/preprocessor/iteration/local.hpp>
|
||||
@@ -123,7 +123,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
return (Radix <= 10 || (ch >= '0' && ch <= '9'))
|
||||
? ch - '0'
|
||||
: char_encoding::ascii::tolower(ch) - 'a' + 10;
|
||||
: traits::char_encoding_traits<Char>::encoding_type::tolower(ch) - 'a' + 10;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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_SPIRIT_X3_SUPPORT_TRAITS_CHAR_ENCODING_TRAITS_HPP
|
||||
#define BOOST_SPIRIT_X3_SUPPORT_TRAITS_CHAR_ENCODING_TRAITS_HPP
|
||||
|
||||
#include <boost/spirit/home/x3/char/char.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/char/literal_char.hpp>
|
||||
#include <boost/spirit/home/x3/string/literal_string.hpp>
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename Encoding>
|
||||
struct char_encoding_traits_impl
|
||||
{
|
||||
using encoding_type = Encoding;
|
||||
|
||||
template <class... Args>
|
||||
[[nodiscard]] static constexpr auto lit(Args&&... args)
|
||||
noexcept(noexcept(Encoding::lit(std::forward<Args>(args)...)))
|
||||
{
|
||||
return Encoding::lit(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
[[nodiscard]] static constexpr auto string(Args&&... args)
|
||||
noexcept(noexcept(Encoding::string(std::forward<Args>(args)...)))
|
||||
{
|
||||
return Encoding::string(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
|
||||
template <traits::CharLike CharT>
|
||||
struct char_encoding_traits;
|
||||
|
||||
template <>
|
||||
struct char_encoding_traits<char> : detail::char_encoding_traits_impl<char_encoding::standard> {};
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
template <>
|
||||
struct char_encoding_traits<wchar_t> : detail::char_encoding_traits_impl<char_encoding::standard_wide> {};
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
template <>
|
||||
struct char_encoding_traits<char32_t> : detail::char_encoding_traits_impl<char_encoding::unicode> {};
|
||||
#endif
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -9,16 +10,16 @@
|
||||
#define BOOST_SPIRIT_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_variant.hpp>
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/support/char_encoding/unicode.hpp>
|
||||
# include <boost/spirit/home/x3/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
namespace boost::spirit::x3::traits
|
||||
{
|
||||
template <typename Out, typename T>
|
||||
void print_attribute(Out& out, T const& val);
|
||||
@@ -165,6 +166,6 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
print_attribute_debug<Out, T>::call(out, val);
|
||||
}
|
||||
}}}}
|
||||
} // boost::spirit::x3::traits
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2010 Bryce Lelbach
|
||||
Copyright (c) 2010 Bryce Lelbach
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -9,146 +10,113 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_STRING_TRAITS_OCTOBER_2008_1252PM)
|
||||
#define BOOST_SPIRIT_X3_STRING_TRAITS_OCTOBER_2008_1252PM
|
||||
|
||||
#if defined(BOOST_SPIRIT_UNICODE) && !defined(BOOST_SPIRIT_X3_UNICODE)
|
||||
# error "`BOOST_SPIRIT_UNICODE` has no effect on X3. #define `BOOST_SPIRIT_X3_UNICODE`"
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_SPIRIT_X3_NO_STANDARD_WIDE) && !defined(BOOST_SPIRIT_X3_NO_STANDARD_WIDE)
|
||||
# error "`BOOST_SPIRIT_X3_NO_STANDARD_WIDE` has no effect on X3. #define `BOOST_SPIRIT_X3_NO_STANDARD_WIDE`"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
namespace boost::spirit::x3::char_encoding
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get the C string from a string
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename String>
|
||||
struct extract_c_string;
|
||||
struct standard;
|
||||
|
||||
template <typename String>
|
||||
struct extract_c_string
|
||||
{
|
||||
template <typename T>
|
||||
static T const* call (T* str)
|
||||
{
|
||||
return (T const*)str;
|
||||
}
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
struct standard_wide;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
static T const* call (T const* str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
};
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
struct unicode;
|
||||
#endif
|
||||
} // boost::spirit::x3::char_encoding
|
||||
|
||||
// Forwarder that strips const
|
||||
namespace boost::spirit::x3::traits
|
||||
{
|
||||
template <typename T>
|
||||
struct extract_c_string<T const>
|
||||
{
|
||||
static decltype(auto) call(T const str)
|
||||
{
|
||||
return extract_c_string<T>::call(str);
|
||||
}
|
||||
};
|
||||
concept CharLike =
|
||||
std::same_as<std::remove_cvref_t<T>, char> ||
|
||||
std::same_as<std::remove_cvref_t<T>, wchar_t> ||
|
||||
std::same_as<std::remove_cvref_t<T>, char8_t> ||
|
||||
std::same_as<std::remove_cvref_t<T>, char16_t> ||
|
||||
std::same_as<std::remove_cvref_t<T>, char32_t>;
|
||||
|
||||
// Forwarder that strips references
|
||||
template <typename T>
|
||||
struct extract_c_string<T&>
|
||||
{
|
||||
static decltype(auto) call(T& str)
|
||||
{
|
||||
return extract_c_string<T>::call(str);
|
||||
}
|
||||
};
|
||||
// Spirit has historically converted "c" to 'c'.
|
||||
//
|
||||
// While we think it's still useful to retain the conversion,
|
||||
// we need to avoid further conversion to `std::basic_string_view`,
|
||||
// which leads to performance overhead. This trait enables
|
||||
// detection of such arrays.
|
||||
//
|
||||
// Note that the status quo introduces ambiguity in determining
|
||||
// {'c', '\0'} and {'c', 'd'}, but we're not aware of any practical
|
||||
// usage of non-null-terminated character array in the context of
|
||||
// DSL on parser combinator.
|
||||
//
|
||||
// However, if compelling use cases emerge, we may revise these
|
||||
// semantics. Versioned as `X3` for forward compatibility.
|
||||
template <typename T, typename CharT>
|
||||
concept X3VagueArrayOf2Chars =
|
||||
std::same_as<std::remove_all_extents_t<std::remove_cvref_t<T>>, CharT> &&
|
||||
std::is_bounded_array_v<std::remove_cvref_t<T>> &&
|
||||
std::extent_v<std::remove_cvref_t<T>> == 2;
|
||||
|
||||
// Forwarder that strips const references
|
||||
template <typename T>
|
||||
struct extract_c_string<T const&>
|
||||
{
|
||||
static decltype(auto) call(T const& str)
|
||||
{
|
||||
return extract_c_string<T>::call(str);
|
||||
}
|
||||
};
|
||||
// Main utility to guide `char_`, `lit` and `string` to be
|
||||
// resolved into either `x3::literal_char` or `x3::literal_string`.
|
||||
//
|
||||
// This may also be used in other codes which require the same
|
||||
// semantics.
|
||||
template <typename T, typename CharT>
|
||||
concept CppStringLike =
|
||||
// This avoids converting `CharT[2]` to `std::basic_string_view`.
|
||||
(!X3VagueArrayOf2Chars<T, CharT>) &&
|
||||
// All other types that are *naturally* convertible to `std::basic_string_view`.
|
||||
std::convertible_to<std::decay_t<T>, std::basic_string_view<CharT>>;
|
||||
|
||||
template <typename T, typename Traits, typename Allocator>
|
||||
struct extract_c_string<std::basic_string<T, Traits, Allocator> >
|
||||
{
|
||||
typedef std::basic_string<T, Traits, Allocator> string;
|
||||
// Mixing incompatible character types is semantically wrong.
|
||||
// Don't do that. It may even lead to security vulnerabilities.
|
||||
template <typename T, typename ExpectedCharT>
|
||||
concept CharIncompatibleWith =
|
||||
CharLike<T> &&
|
||||
!std::same_as<std::remove_cvref_t<T>, ExpectedCharT>;
|
||||
|
||||
static T const* call (string const& str)
|
||||
{
|
||||
return str.c_str();
|
||||
}
|
||||
};
|
||||
// Mixing incompatible character types is semantically wrong.
|
||||
// Don't do that. It may even lead to security vulnerabilities.
|
||||
template <typename T, typename ExpectedCharT>
|
||||
concept StringLikeIncompatibleWith =
|
||||
CharLike<std::remove_const_t<std::remove_pointer_t<std::decay_t<T>>>> &&
|
||||
!std::convertible_to<T, std::basic_string_view<ExpectedCharT>>;
|
||||
|
||||
template <typename T>
|
||||
decltype(auto) get_c_string(T* str)
|
||||
{
|
||||
return extract_c_string<T*>::call(str);
|
||||
}
|
||||
namespace detail {
|
||||
template <CharLike CharT> struct char_encoding_for_impl;
|
||||
template <> struct char_encoding_for_impl<char> { using type = char_encoding::standard; };
|
||||
|
||||
template <typename T>
|
||||
decltype(auto) get_c_string(T const* str)
|
||||
{
|
||||
return extract_c_string<T const*>::call(str);
|
||||
}
|
||||
#ifndef BOOST_SPIRIT_X3_NO_STANDARD_WIDE
|
||||
template <> struct char_encoding_for_impl<wchar_t> { using type = char_encoding::standard_wide; };
|
||||
#endif
|
||||
|
||||
template <typename String>
|
||||
decltype(auto) get_c_string(String& str)
|
||||
{
|
||||
return extract_c_string<String>::call(str);
|
||||
}
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
template <> struct char_encoding_for_impl<char8_t> { using type = char_encoding::unicode; };
|
||||
template <> struct char_encoding_for_impl<char16_t> { using type = char_encoding::unicode; };
|
||||
template <> struct char_encoding_for_impl<char32_t> { using type = char_encoding::unicode; };
|
||||
#endif
|
||||
} // detail
|
||||
|
||||
template <typename String>
|
||||
decltype(auto) get_c_string(String const& str)
|
||||
{
|
||||
return extract_c_string<String>::call(str);
|
||||
}
|
||||
template <class T>
|
||||
using maybe_owning_string = std::conditional_t<
|
||||
std::is_pointer_v<std::decay_t<T>>,
|
||||
std::basic_string_view<std::remove_const_t<std::remove_pointer_t<std::decay_t<T>>>>,
|
||||
std::remove_cvref_t<T>
|
||||
>;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get the begin/end iterators from a string
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <CharLike CharT>
|
||||
using char_encoding_for = typename detail::char_encoding_for_impl<CharT>::type;
|
||||
|
||||
// Implementation for C-style strings.
|
||||
|
||||
template <typename T>
|
||||
inline T const* get_string_begin(T const* str) { return str; }
|
||||
|
||||
template <typename T>
|
||||
inline T* get_string_begin(T* str) { return str; }
|
||||
|
||||
template <typename T>
|
||||
inline T const* get_string_end(T const* str)
|
||||
{
|
||||
T const* last = str;
|
||||
while (*last)
|
||||
last++;
|
||||
return last;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* get_string_end(T* str)
|
||||
{
|
||||
T* last = str;
|
||||
while (*last)
|
||||
last++;
|
||||
return last;
|
||||
}
|
||||
|
||||
// Implementation for containers (includes basic_string).
|
||||
template <typename T, typename Str>
|
||||
inline typename Str::const_iterator get_string_begin(Str const& str)
|
||||
{ return str.begin(); }
|
||||
|
||||
template <typename T, typename Str>
|
||||
inline typename Str::iterator
|
||||
get_string_begin(Str& str)
|
||||
{ return str.begin(); }
|
||||
|
||||
template <typename T, typename Str>
|
||||
inline typename Str::const_iterator get_string_end(Str const& str)
|
||||
{ return str.end(); }
|
||||
|
||||
template <typename T, typename Str>
|
||||
inline typename Str::iterator
|
||||
get_string_end(Str& str)
|
||||
{ return str.end(); }
|
||||
}}}}
|
||||
} // boost::spirit::x3::traits
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2023 Nikita Kniazev
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -9,121 +10,165 @@
|
||||
#define BOOST_SPIRIT_X3_UC_TYPES_NOVEMBER_23_2008_0840PM
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
#include <cassert>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
{
|
||||
typedef char32_t ucs4_char;
|
||||
typedef char utf8_char;
|
||||
typedef std::basic_string<ucs4_char> ucs4_string;
|
||||
typedef std::basic_string<utf8_char> utf8_string;
|
||||
using ucs4_char = char32_t;
|
||||
using utf8_char = char;
|
||||
using ucs4_string = std::basic_string<ucs4_char>;
|
||||
using utf8_string = std::basic_string<utf8_char>;
|
||||
|
||||
namespace detail {
|
||||
inline void utf8_put_encode(utf8_string& out, ucs4_char x)
|
||||
{
|
||||
// https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf D90
|
||||
if (BOOST_UNLIKELY(x > 0x10FFFFul || (0xD7FFul < x && x < 0xE000ul)))
|
||||
x = 0xFFFDul;
|
||||
namespace detail {
|
||||
constexpr void utf8_put_encode(utf8_string& out, ucs4_char x) noexcept
|
||||
{
|
||||
// https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf D90
|
||||
if (x > 0x10FFFFul || (0xD7FFul < x && x < 0xE000ul)) [[unlikely]]
|
||||
x = 0xFFFDul;
|
||||
|
||||
// Table 3-6. UTF-8 Bit Distribution
|
||||
if (x < 0x80ul) {
|
||||
out.push_back(static_cast<unsigned char>(x));
|
||||
}
|
||||
else if (x < 0x800ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xC0ul + (x >> 6)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else if (x < 0x10000ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xE0ul + (x >> 12)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else {
|
||||
out.push_back(static_cast<unsigned char>(0xF0ul + (x >> 18)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 12) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
// Table 3-6. UTF-8 Bit Distribution
|
||||
if (x < 0x80ul) {
|
||||
out.push_back(static_cast<unsigned char>(x));
|
||||
}
|
||||
else if (x < 0x800ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xC0ul + (x >> 6)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else if (x < 0x10000ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xE0ul + (x >> 12)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else {
|
||||
out.push_back(static_cast<unsigned char>(0xF0ul + (x >> 18)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 12) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline utf8_string to_utf8(Char value)
|
||||
[[nodiscard]] constexpr utf8_string to_utf8(Char value)
|
||||
{
|
||||
utf8_string result;
|
||||
typedef typename std::make_unsigned<Char>::type UChar;
|
||||
using UChar = std::make_unsigned_t<Char>;
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline utf8_string to_utf8(Char const* str)
|
||||
[[nodiscard]] constexpr utf8_string to_utf8(Char const* str)
|
||||
{
|
||||
utf8_string result;
|
||||
typedef typename std::make_unsigned<Char>::type UChar;
|
||||
using UChar = typename std::make_unsigned<Char>::type;
|
||||
while (*str)
|
||||
{
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(*str++));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Char, typename Traits, typename Allocator>
|
||||
inline utf8_string
|
||||
to_utf8(std::basic_string<Char, Traits, Allocator> const& str)
|
||||
template <typename Char, typename Traits>
|
||||
[[nodiscard]] constexpr utf8_string
|
||||
to_utf8(std::basic_string_view<Char, Traits> const str)
|
||||
{
|
||||
utf8_string result;
|
||||
typedef typename std::make_unsigned<Char>::type UChar;
|
||||
using UChar = typename std::make_unsigned<Char>::type;
|
||||
for (Char ch : str)
|
||||
{
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(ch));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Char, typename Traits>
|
||||
[[nodiscard]] constexpr utf8_string
|
||||
to_utf8(std::basic_string<Char, Traits> const& str)
|
||||
{
|
||||
utf8_string result;
|
||||
using UChar = typename std::make_unsigned<Char>::type;
|
||||
for (Char ch : str)
|
||||
{
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(ch));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Assume wchar_t content is UTF-16 on MSVC, or mingw/wineg++ with -fshort-wchar
|
||||
#if defined(_MSC_VER) || defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2
|
||||
inline utf8_string to_utf8(wchar_t value)
|
||||
[[nodiscard]] constexpr utf8_string to_utf8(wchar_t value)
|
||||
{
|
||||
utf8_string result;
|
||||
detail::utf8_put_encode(result, static_cast<std::make_unsigned<wchar_t>::type>(value));
|
||||
detail::utf8_put_encode(result, static_cast<std::make_unsigned_t<wchar_t>>(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
inline ucs4_char decode_utf16(wchar_t const*& s)
|
||||
template <std::forward_iterator It>
|
||||
requires std::is_same_v<std::remove_const_t<std::iter_value_t<It>>, wchar_t>
|
||||
[[nodiscard]] constexpr ucs4_char decode_utf16(It& s) noexcept
|
||||
{
|
||||
typedef std::make_unsigned<wchar_t>::type uwchar_t;
|
||||
using uwchar_t = std::make_unsigned<wchar_t>::type;
|
||||
|
||||
uwchar_t x(*s);
|
||||
if (x < 0xD800ul || x > 0xDFFFul)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
// expected high-surrogate
|
||||
if (BOOST_UNLIKELY((x >> 10) != 0b110110ul))
|
||||
if ((x >> 10) != 0b110110ul) [[unlikely]]
|
||||
{
|
||||
return 0xFFFDul;
|
||||
}
|
||||
|
||||
uwchar_t y(*++s);
|
||||
// expected low-surrogate
|
||||
if (BOOST_UNLIKELY((y >> 10) != 0b110111ul))
|
||||
if ((y >> 10) != 0b110111ul) [[unlikely]]
|
||||
{
|
||||
return 0xFFFDul;
|
||||
}
|
||||
|
||||
return ((x & 0x3FFul) << 10) + (y & 0x3FFul) + 0x10000ul;
|
||||
}
|
||||
}
|
||||
|
||||
inline utf8_string to_utf8(wchar_t const* str)
|
||||
template <typename Traits>
|
||||
[[nodiscard]] constexpr utf8_string
|
||||
to_utf8(std::basic_string_view<wchar_t, Traits> const str)
|
||||
{
|
||||
utf8_string result;
|
||||
for (ucs4_char c; (c = detail::decode_utf16(str)) != ucs4_char(); ++str)
|
||||
detail::utf8_put_encode(result, c);
|
||||
for (auto it = str.begin(); it != str.end(); ++it)
|
||||
{
|
||||
detail::utf8_put_encode(result, detail::decode_utf16(it));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Traits, typename Allocator>
|
||||
inline utf8_string
|
||||
to_utf8(std::basic_string<wchar_t, Traits, Allocator> const& str)
|
||||
[[nodiscard]] constexpr utf8_string to_utf8(wchar_t const* str)
|
||||
{
|
||||
return to_utf8(str.c_str());
|
||||
return x3::to_utf8(std::basic_string_view(str));
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
[[nodiscard]] constexpr utf8_string
|
||||
to_utf8(std::basic_string<wchar_t, Traits> const& str)
|
||||
{
|
||||
utf8_string result;
|
||||
for (auto it = str.begin(); it != str.end(); ++it)
|
||||
{
|
||||
detail::utf8_put_encode(result, detail::decode_utf16(it));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}}}
|
||||
} // boost::spirit::x3
|
||||
|
||||
#endif
|
||||
|
||||
@@ -91,8 +91,7 @@ run extract_int.cpp ;
|
||||
run int1.cpp ;
|
||||
run kleene.cpp ;
|
||||
run lexeme.cpp ;
|
||||
run lit1.cpp ;
|
||||
run lit2.cpp ;
|
||||
run lit.cpp ;
|
||||
run list.cpp ;
|
||||
run matches.cpp ;
|
||||
run no_case.cpp ;
|
||||
|
||||
@@ -1,11 +1,38 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2011 Bryce Lelbach
|
||||
Copyright (c) 2011 Bryce Lelbach
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
==============================================================================*/
|
||||
#include "bool.hpp"
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
#include <string_view>
|
||||
#include <iterator>
|
||||
|
||||
struct backwards_bool_policies : boost::spirit::x3::bool_policies<>
|
||||
{
|
||||
// we want to interpret a 'true' spelled backwards as 'false'
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute, typename CaseCompare>
|
||||
[[nodiscard]] static constexpr bool
|
||||
parse_false(
|
||||
It& first, Se const& last, Attribute& attr, CaseCompare const& case_compare
|
||||
)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
namespace x3 = boost::spirit::x3;
|
||||
if (x3::detail::string_parse("eurt"sv, first, last, x3::unused, case_compare))
|
||||
{
|
||||
x3::traits::move_to(false, attr); // result is false
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -27,61 +54,65 @@ int main()
|
||||
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(true_);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(false_);
|
||||
|
||||
|
||||
BOOST_TEST(test("true", true_));
|
||||
BOOST_TEST(!test("true", false_));
|
||||
BOOST_TEST(test("false", false_));
|
||||
BOOST_TEST(!test("false", true_));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
using boost::spirit::x3::true_;
|
||||
using boost::spirit::x3::false_;
|
||||
using boost::spirit::x3::no_case;
|
||||
|
||||
|
||||
BOOST_TEST(test("True", no_case[bool_]));
|
||||
BOOST_TEST(test("False", no_case[bool_]));
|
||||
BOOST_TEST(test("True", no_case[true_]));
|
||||
BOOST_TEST(test("False", no_case[false_]));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
bool b = false;
|
||||
BOOST_TEST(test_attr("true", bool_, b) && b);
|
||||
BOOST_TEST(test_attr("false", bool_, b) && !b);
|
||||
BOOST_TEST(!test_attr("fasle", bool_, b));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
typedef boost::spirit::x3::bool_parser<bool, boost::spirit::char_encoding::standard, backwards_bool_policies>
|
||||
backwards_bool_type;
|
||||
using backwards_bool_type = boost::spirit::x3::bool_parser<bool, boost::spirit::x3::char_encoding::standard, backwards_bool_policies>;
|
||||
constexpr backwards_bool_type backwards_bool{};
|
||||
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(backwards_bool);
|
||||
|
||||
|
||||
BOOST_TEST(test("true", backwards_bool));
|
||||
BOOST_TEST(test("eurt", backwards_bool));
|
||||
BOOST_TEST(!test("false", backwards_bool));
|
||||
BOOST_TEST(!test("fasle", backwards_bool));
|
||||
|
||||
|
||||
bool b = false;
|
||||
BOOST_TEST(test_attr("true", backwards_bool, b) && b);
|
||||
BOOST_TEST(test_attr("eurt", backwards_bool, b) && !b);
|
||||
BOOST_TEST(!test_attr("false", backwards_bool, b));
|
||||
BOOST_TEST(!test_attr("fasle", backwards_bool, b));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
typedef boost::spirit::x3::bool_parser<test_bool_type, boost::spirit::char_encoding::standard>
|
||||
bool_test_type;
|
||||
struct test_bool_type
|
||||
{
|
||||
test_bool_type(bool b = false) : b(b) {} // provide conversion
|
||||
bool b;
|
||||
};
|
||||
|
||||
using bool_test_type = boost::spirit::x3::bool_parser<test_bool_type, boost::spirit::x3::char_encoding::standard>;
|
||||
constexpr bool_test_type test_bool{};
|
||||
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(test_bool);
|
||||
|
||||
|
||||
BOOST_TEST(test("true", test_bool));
|
||||
BOOST_TEST(test("false", test_bool));
|
||||
BOOST_TEST(!test("fasle", test_bool));
|
||||
|
||||
|
||||
test_bool_type b = false;
|
||||
BOOST_TEST(test_attr("true", test_bool, b) && b.b);
|
||||
BOOST_TEST(test_attr("false", test_bool, b) && !b.b);
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2011 Bryce Lelbach
|
||||
|
||||
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)
|
||||
==============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_TEST_QI_BOOL)
|
||||
#define BOOST_SPIRIT_TEST_QI_BOOL
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include "test.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
struct backwards_bool_policies : boost::spirit::x3::bool_policies<>
|
||||
{
|
||||
// we want to interpret a 'true' spelled backwards as 'false'
|
||||
template <typename Iterator, typename Attribute, typename CaseCompare>
|
||||
static bool
|
||||
parse_false(Iterator& first, Iterator const& last, Attribute& attr, CaseCompare const& case_compare)
|
||||
{
|
||||
namespace spirit = boost::spirit;
|
||||
namespace x3 = boost::spirit::x3;
|
||||
if (x3::detail::string_parse("eurt", first, last, x3::unused, case_compare))
|
||||
{
|
||||
x3::traits::move_to(false, attr); // result is false
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
struct test_bool_type
|
||||
{
|
||||
test_bool_type(bool b = false) : b(b) {} // provide conversion
|
||||
bool b;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,31 +1,32 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2019 Christian Mazakas
|
||||
Copyright (c) 2019 Christian Mazakas
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
=============================================================================*/
|
||||
|
||||
#define BOOST_SPIRIT_UNICODE
|
||||
#define BOOST_SPIRIT_X3_UNICODE
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
#include <boost/utility/string_view.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
int
|
||||
main()
|
||||
int main()
|
||||
{
|
||||
using spirit_test::test;
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
using namespace boost::spirit::x3::standard;
|
||||
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(char_);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(char_('x'));
|
||||
@@ -69,7 +70,7 @@ main()
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
using namespace boost::spirit::x3::standard;
|
||||
|
||||
BOOST_TEST(test(" x", 'x', space));
|
||||
BOOST_TEST(test(L" x", L'x', space));
|
||||
@@ -125,11 +126,11 @@ main()
|
||||
auto const sub_delims = char_(U"!$&'()*+,;=");
|
||||
|
||||
auto const delims =
|
||||
std::vector<boost::u32string_view>{U"!", U"$", U"&", U"'", U"(", U")", U"*", U"+",
|
||||
std::vector<std::u32string_view>{U"!", U"$", U"&", U"'", U"(", U")", U"*", U"+",
|
||||
U",", U";", U"="};
|
||||
|
||||
auto const matched_all_sub_delims =
|
||||
std::all_of(delims.begin(), delims.end(), [&](auto const delim) -> bool {
|
||||
std::ranges::all_of(delims, [&](auto const delim) -> bool {
|
||||
return test(delim, sub_delims);
|
||||
});
|
||||
|
||||
@@ -143,18 +144,18 @@ main()
|
||||
auto const chars = char_(U"\u0024\u00a2\u0939\u20ac\U00010348");
|
||||
|
||||
auto const test_strings =
|
||||
std::vector<boost::u32string_view>{U"\u0024", U"\u00a2", U"\u0939", U"\u20ac",
|
||||
std::vector<std::u32string_view>{U"\u0024", U"\u00a2", U"\u0939", U"\u20ac",
|
||||
U"\U00010348"};
|
||||
|
||||
auto const bad_test_strings = std::vector<boost::u32string_view>{U"a", U"B", U"c", U"\u0409"};
|
||||
auto const bad_test_strings = std::vector<std::u32string_view>{U"a", U"B", U"c", U"\u0409"};
|
||||
|
||||
auto const all_matched =
|
||||
std::all_of(test_strings.begin(), test_strings.end(), [&](auto const test_str) -> bool {
|
||||
std::ranges::all_of(test_strings, [&](auto const test_str) -> bool {
|
||||
return test(test_str, chars);
|
||||
});
|
||||
|
||||
auto const none_matched =
|
||||
std::all_of(bad_test_strings.begin(), bad_test_strings.end(), [&](auto const bad_test_str) -> bool {
|
||||
std::ranges::all_of(bad_test_strings, [&](auto const bad_test_str) -> bool {
|
||||
return !test(bad_test_str, chars);
|
||||
});
|
||||
|
||||
@@ -164,50 +165,38 @@ main()
|
||||
|
||||
|
||||
{ // single char strings!
|
||||
namespace ascii = boost::spirit::x3::ascii;
|
||||
namespace wide = boost::spirit::x3::standard_wide;
|
||||
namespace standard = boost::spirit::x3::standard;
|
||||
namespace wide = boost::spirit::x3::standard_wide;
|
||||
|
||||
BOOST_TEST(test("x", "x"));
|
||||
BOOST_TEST(test(L"x", L"x"));
|
||||
BOOST_TEST(test("x", ascii::char_("x")));
|
||||
BOOST_TEST(test("x", standard::char_("x")));
|
||||
BOOST_TEST(test(L"x", wide::char_(L"x")));
|
||||
|
||||
BOOST_TEST(test("x", ascii::char_("a", "z")));
|
||||
BOOST_TEST(test("x", standard::char_("a", "z")));
|
||||
BOOST_TEST(test(L"x", wide::char_(L"a", L"z")));
|
||||
}
|
||||
|
||||
{
|
||||
// chsets
|
||||
namespace ascii = boost::spirit::x3::ascii;
|
||||
namespace standard = boost::spirit::x3::standard;
|
||||
namespace wide = boost::spirit::x3::standard_wide;
|
||||
|
||||
BOOST_TEST(test("x", ascii::char_("a-z")));
|
||||
BOOST_TEST(!test("1", ascii::char_("a-z")));
|
||||
BOOST_TEST(test("1", ascii::char_("a-z0-9")));
|
||||
BOOST_TEST(test("x", standard::char_("a-z")));
|
||||
BOOST_TEST(!test("1", standard::char_("a-z")));
|
||||
BOOST_TEST(test("1", standard::char_("a-z0-9")));
|
||||
|
||||
BOOST_TEST(test("x", wide::char_(L"a-z")));
|
||||
BOOST_TEST(!test("1", wide::char_(L"a-z")));
|
||||
BOOST_TEST(test("1", wide::char_(L"a-z0-9")));
|
||||
|
||||
std::string set = "a-z0-9";
|
||||
BOOST_TEST(test("x", ascii::char_(set)));
|
||||
BOOST_TEST(test("x", standard::char_(set)));
|
||||
|
||||
#ifdef SPIRIT_NO_COMPILE_CHECK
|
||||
test("", ascii::char_(L"a-z0-9"));
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
namespace ascii = boost::spirit::x3::ascii;
|
||||
char const* input = "\x80";
|
||||
|
||||
// ascii > 7 bits (this should fail, not assert!)
|
||||
BOOST_TEST(!test(input, ascii::char_));
|
||||
BOOST_TEST(!test(input, ascii::char_('a')));
|
||||
BOOST_TEST(!test(input, ascii::alnum));
|
||||
BOOST_TEST(!test(input, ascii::char_("a-z")));
|
||||
BOOST_TEST(!test(input, ascii::char_('0', '9')));
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 Joel de Guzman
|
||||
Copyright (c) 2001-2010 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
=============================================================================*/
|
||||
|
||||
#define BOOST_SPIRIT_UNICODE
|
||||
#define BOOST_SPIRIT_X3_UNICODE
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include "test.hpp"
|
||||
|
||||
int
|
||||
main()
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
using spirit_test::test;
|
||||
using spirit_test::test_failure;
|
||||
@@ -23,113 +25,6 @@ main()
|
||||
|
||||
using boost::spirit::x3::unused_type;
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(alnum);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(alpha);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(digit);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(xdigit);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(cntrl);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(graph);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(lower);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(print);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(punct);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(space);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(blank);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(upper);
|
||||
BOOST_TEST(test("1", alnum));
|
||||
BOOST_TEST(!test(" ", alnum));
|
||||
BOOST_TEST(!test("1", alpha));
|
||||
BOOST_TEST(test("x", alpha));
|
||||
BOOST_TEST(test(" ", blank));
|
||||
BOOST_TEST(!test("x", blank));
|
||||
BOOST_TEST(test("1", digit));
|
||||
BOOST_TEST(!test("x", digit));
|
||||
BOOST_TEST(test("a", lower));
|
||||
BOOST_TEST(!test("A", lower));
|
||||
BOOST_TEST(test("!", punct));
|
||||
BOOST_TEST(!test("x", punct));
|
||||
BOOST_TEST(test(" ", space));
|
||||
BOOST_TEST(test("\n", space));
|
||||
BOOST_TEST(test("\r", space));
|
||||
BOOST_TEST(test("\t", space));
|
||||
BOOST_TEST(test("A", upper));
|
||||
BOOST_TEST(!test("a", upper));
|
||||
BOOST_TEST(test("A", xdigit));
|
||||
BOOST_TEST(test("0", xdigit));
|
||||
BOOST_TEST(test("f", xdigit));
|
||||
BOOST_TEST(!test("g", xdigit));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
BOOST_TEST(!test("1", ~alnum));
|
||||
BOOST_TEST(test(" ", ~alnum));
|
||||
BOOST_TEST(test("1", ~alpha));
|
||||
BOOST_TEST(!test("x", ~alpha));
|
||||
BOOST_TEST(!test(" ", ~blank));
|
||||
BOOST_TEST(test("x", ~blank));
|
||||
BOOST_TEST(!test("1", ~digit));
|
||||
BOOST_TEST(test("x", ~digit));
|
||||
BOOST_TEST(!test("a", ~lower));
|
||||
BOOST_TEST(test("A", ~lower));
|
||||
BOOST_TEST(!test("!", ~punct));
|
||||
BOOST_TEST(test("x", ~punct));
|
||||
BOOST_TEST(!test(" ", ~space));
|
||||
BOOST_TEST(!test("\n", ~space));
|
||||
BOOST_TEST(!test("\r", ~space));
|
||||
BOOST_TEST(!test("\t", ~space));
|
||||
BOOST_TEST(!test("A", ~upper));
|
||||
BOOST_TEST(test("a", ~upper));
|
||||
BOOST_TEST(!test("A", ~xdigit));
|
||||
BOOST_TEST(!test("0", ~xdigit));
|
||||
BOOST_TEST(!test("f", ~xdigit));
|
||||
BOOST_TEST(test("g", ~xdigit));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::iso8859_1;
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(alnum);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(alpha);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(digit);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(xdigit);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(cntrl);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(graph);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(lower);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(print);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(punct);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(space);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(blank);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(upper);
|
||||
BOOST_TEST(test("1", alnum));
|
||||
BOOST_TEST(!test(" ", alnum));
|
||||
BOOST_TEST(!test("1", alpha));
|
||||
BOOST_TEST(test("x", alpha));
|
||||
BOOST_TEST(test(" ", blank));
|
||||
BOOST_TEST(!test("x", blank));
|
||||
BOOST_TEST(test("1", digit));
|
||||
BOOST_TEST(!test("x", digit));
|
||||
BOOST_TEST(test("a", lower));
|
||||
BOOST_TEST(!test("A", lower));
|
||||
BOOST_TEST(test("!", punct));
|
||||
BOOST_TEST(!test("x", punct));
|
||||
BOOST_TEST(test(" ", space));
|
||||
BOOST_TEST(test("\n", space));
|
||||
BOOST_TEST(test("\r", space));
|
||||
BOOST_TEST(test("\t", space));
|
||||
BOOST_TEST(test("A", upper));
|
||||
BOOST_TEST(!test("a", upper));
|
||||
BOOST_TEST(test("A", xdigit));
|
||||
BOOST_TEST(test("0", xdigit));
|
||||
BOOST_TEST(test("f", xdigit));
|
||||
BOOST_TEST(!test("g", xdigit));
|
||||
|
||||
// test extended ASCII characters
|
||||
BOOST_TEST(test("\xE9", alpha));
|
||||
BOOST_TEST(test("\xE9", lower));
|
||||
BOOST_TEST(!test("\xE9", upper));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::standard;
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(alnum);
|
||||
@@ -221,42 +116,42 @@ main()
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(space);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(blank);
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(upper);
|
||||
BOOST_TEST(test(L"1", alnum));
|
||||
BOOST_TEST(!test(L" ", alnum));
|
||||
BOOST_TEST(!test(L"1", alpha));
|
||||
BOOST_TEST(test(L"x", alpha));
|
||||
BOOST_TEST(test(L" ", blank));
|
||||
BOOST_TEST(!test(L"x", blank));
|
||||
BOOST_TEST(test(L"1", digit));
|
||||
BOOST_TEST(!test(L"x", digit));
|
||||
BOOST_TEST(test(L"a", lower));
|
||||
BOOST_TEST(!test(L"A", lower));
|
||||
BOOST_TEST(test(L"!", punct));
|
||||
BOOST_TEST(!test(L"x", punct));
|
||||
BOOST_TEST(test(L" ", space));
|
||||
BOOST_TEST(test(L"\n", space));
|
||||
BOOST_TEST(test(L"\r", space));
|
||||
BOOST_TEST(test(L"\t", space));
|
||||
BOOST_TEST(test(L"A", upper));
|
||||
BOOST_TEST(!test(L"a", upper));
|
||||
BOOST_TEST(test(L"A", xdigit));
|
||||
BOOST_TEST(test(L"0", xdigit));
|
||||
BOOST_TEST(test(L"f", xdigit));
|
||||
BOOST_TEST(!test(L"g", xdigit));
|
||||
BOOST_TEST(test(U"1", alnum));
|
||||
BOOST_TEST(!test(U" ", alnum));
|
||||
BOOST_TEST(!test(U"1", alpha));
|
||||
BOOST_TEST(test(U"x", alpha));
|
||||
BOOST_TEST(test(U" ", blank));
|
||||
BOOST_TEST(!test(U"x", blank));
|
||||
BOOST_TEST(test(U"1", digit));
|
||||
BOOST_TEST(!test(U"x", digit));
|
||||
BOOST_TEST(test(U"a", lower));
|
||||
BOOST_TEST(!test(U"A", lower));
|
||||
BOOST_TEST(test(U"!", punct));
|
||||
BOOST_TEST(!test(U"x", punct));
|
||||
BOOST_TEST(test(U" ", space));
|
||||
BOOST_TEST(test(U"\n", space));
|
||||
BOOST_TEST(test(U"\r", space));
|
||||
BOOST_TEST(test(U"\t", space));
|
||||
BOOST_TEST(test(U"A", upper));
|
||||
BOOST_TEST(!test(U"a", upper));
|
||||
BOOST_TEST(test(U"A", xdigit));
|
||||
BOOST_TEST(test(U"0", xdigit));
|
||||
BOOST_TEST(test(U"f", xdigit));
|
||||
BOOST_TEST(!test(U"g", xdigit));
|
||||
|
||||
BOOST_TEST(test(L"A", alphabetic));
|
||||
BOOST_TEST(test(L"9", decimal_number));
|
||||
BOOST_TEST(test(L"\u2800", braille));
|
||||
BOOST_TEST(!test(L" ", braille));
|
||||
BOOST_TEST(test(L" ", ~braille));
|
||||
// $$$ TODO $$$ Add more unicode tests
|
||||
BOOST_TEST(test(U"A", alphabetic));
|
||||
BOOST_TEST(test(U"9", decimal_number));
|
||||
BOOST_TEST(test(U"\u2800", braille));
|
||||
BOOST_TEST(!test(U" ", braille));
|
||||
BOOST_TEST(test(U" ", ~braille));
|
||||
// TODO: Add more unicode tests
|
||||
}
|
||||
|
||||
{ // test invalid unicode literals
|
||||
using namespace boost::spirit::x3::unicode;
|
||||
|
||||
auto const invalid_unicode = char32_t{0x7FFFFFFF};
|
||||
auto const input = boost::u32string_view(&invalid_unicode, 1);
|
||||
auto const input = std::u32string_view(&invalid_unicode, 1);
|
||||
|
||||
BOOST_TEST(test_failure(input, char_));
|
||||
|
||||
@@ -268,16 +163,11 @@ main()
|
||||
}
|
||||
|
||||
{ // test attribute extraction
|
||||
using boost::spirit::x3::traits::attribute_of;
|
||||
using boost::spirit::x3::iso8859_1::alpha;
|
||||
using boost::spirit::x3::iso8859_1::alpha_type;
|
||||
using boost::spirit::x3::traits::attribute_of_t;
|
||||
using boost::spirit::x3::standard::alpha;
|
||||
using boost::spirit::x3::standard::alpha_type;
|
||||
|
||||
static_assert(
|
||||
boost::is_same<
|
||||
attribute_of<alpha_type, unused_type>::type
|
||||
, unsigned char>::value
|
||||
, "Wrong attribute type!"
|
||||
);
|
||||
static_assert(std::is_same_v<attribute_of_t<alpha_type, unused_type>, char>);
|
||||
|
||||
int attr = 0;
|
||||
BOOST_TEST(test_attr("a", alpha, attr));
|
||||
@@ -285,15 +175,15 @@ main()
|
||||
}
|
||||
|
||||
{ // test attribute extraction
|
||||
using boost::spirit::x3::iso8859_1::alpha;
|
||||
using boost::spirit::x3::iso8859_1::space;
|
||||
using boost::spirit::x3::standard::alpha;
|
||||
using boost::spirit::x3::standard::space;
|
||||
char attr = 0;
|
||||
BOOST_TEST(test_attr(" a", alpha, attr, space));
|
||||
BOOST_TEST(attr == 'a');
|
||||
}
|
||||
|
||||
{ // test action
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
using namespace boost::spirit::x3::standard;
|
||||
using boost::spirit::x3::_attr;
|
||||
char ch;
|
||||
auto f = [&](auto& ctx){ ch = _attr(ctx); };
|
||||
|
||||
162
test/x3/lit.cpp
162
test/x3/lit.cpp
@@ -1,54 +1,164 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
=============================================================================*/
|
||||
|
||||
#undef BOOST_SPIRIT_NO_STANDARD_WIDE
|
||||
|
||||
#ifndef BOOST_SPIRIT_UNICODE
|
||||
# define BOOST_SPIRIT_UNICODE
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_UNICODE
|
||||
# define BOOST_SPIRIT_X3_UNICODE
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
int
|
||||
main()
|
||||
int main()
|
||||
{
|
||||
namespace x3 = boost::spirit::x3;
|
||||
using spirit_test::test;
|
||||
using spirit_test::test_attr;
|
||||
using boost::spirit::x3::lit;
|
||||
using boost::spirit::x3::char_;
|
||||
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(lit("x"));
|
||||
// standard
|
||||
{
|
||||
(void)x3::lit('f'); // deprecated
|
||||
(void)x3::lit("f"); // deprecated
|
||||
(void)x3::lit("foo"); // deprecated
|
||||
(void)x3::standard::lit('f');
|
||||
(void)x3::standard::lit("f");
|
||||
(void)x3::standard::lit("foo");
|
||||
|
||||
(void)x3::char_('f'); // deprecated
|
||||
(void)x3::char_("f"); // deprecated
|
||||
(void)x3::char_("foo"); // deprecated
|
||||
(void)x3::standard::char_('f');
|
||||
(void)x3::standard::char_("f");
|
||||
(void)x3::standard::char_("foo");
|
||||
|
||||
(void)x3::string('f'); // deprecated
|
||||
(void)x3::string("f"); // deprecated
|
||||
(void)x3::string("foo"); // deprecated
|
||||
(void)x3::standard::string('f');
|
||||
(void)x3::standard::string("f");
|
||||
(void)x3::standard::string("foo");
|
||||
}
|
||||
|
||||
// standard_wide
|
||||
{
|
||||
(void)x3::lit(L'f'); // deprecated
|
||||
(void)x3::lit(L"f"); // deprecated
|
||||
(void)x3::lit(L"foo"); // deprecated
|
||||
(void)x3::standard_wide::lit(L'f');
|
||||
(void)x3::standard_wide::lit(L"f");
|
||||
(void)x3::standard_wide::lit(L"foo");
|
||||
|
||||
(void)x3::standard_wide::char_(L'f');
|
||||
(void)x3::standard_wide::char_(L"f");
|
||||
(void)x3::standard_wide::char_(L"foo");
|
||||
|
||||
(void)x3::string(L'f'); // deprecated
|
||||
(void)x3::string(L"f"); // deprecated
|
||||
(void)x3::string(L"foo"); // deprecated
|
||||
(void)x3::standard_wide::string(L'f');
|
||||
(void)x3::standard_wide::string(L"f");
|
||||
(void)x3::standard_wide::string(L"foo");
|
||||
}
|
||||
|
||||
// unicode
|
||||
{
|
||||
(void)x3::unicode::lit(U'f');
|
||||
(void)x3::unicode::lit(U"f");
|
||||
(void)x3::unicode::lit(U"foo");
|
||||
|
||||
(void)x3::unicode::char_(U'f');
|
||||
(void)x3::unicode::char_(U"f");
|
||||
(void)x3::unicode::char_(U"foo");
|
||||
|
||||
(void)x3::unicode::string(U'f');
|
||||
(void)x3::unicode::string(U"f");
|
||||
(void)x3::unicode::string(U"foo");
|
||||
}
|
||||
|
||||
{
|
||||
std::string attr;
|
||||
auto p = char_ >> lit("\n");
|
||||
auto p = x3::standard::char_ >> x3::standard::lit("\n");
|
||||
BOOST_TEST(test_attr("A\n", p, attr));
|
||||
BOOST_TEST(attr == "A");
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
std::string attr;
|
||||
auto p = char_ >> lit("\n");
|
||||
BOOST_TEST(test_attr("A\n", p, attr));
|
||||
BOOST_TEST(attr == "A");
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::iso8859_1;
|
||||
std::string attr;
|
||||
auto p = char_ >> lit("\n");
|
||||
BOOST_TEST(test_attr("É\n", p, attr));
|
||||
BOOST_TEST(attr == "É");
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::standard_wide;
|
||||
std::wstring attr;
|
||||
auto p = char_ >> lit("\n");
|
||||
BOOST_TEST(test_attr(l"É\n", p, attr));
|
||||
BOOST_TEST(attr == "A");
|
||||
auto p = x3::standard_wide::char_ >> x3::standard_wide::lit(L"\n");
|
||||
BOOST_TEST(test_attr(L"É\n", p, attr));
|
||||
BOOST_TEST(attr == L"É");
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
{
|
||||
BOOST_TEST((test("kimpo", x3::standard::lit("kimpo"))));
|
||||
|
||||
std::basic_string<char> s("kimpo");
|
||||
std::basic_string<wchar_t> ws(L"kimpo");
|
||||
BOOST_TEST((test("kimpo", x3::standard::lit(s))));
|
||||
BOOST_TEST((test(L"kimpo", x3::standard_wide::lit(ws))));
|
||||
}
|
||||
|
||||
{
|
||||
std::basic_string<char> s("kimpo");
|
||||
BOOST_TEST((test("kimpo", x3::standard::lit(s))));
|
||||
|
||||
std::basic_string<wchar_t> ws(L"kimpo");
|
||||
BOOST_TEST((test(L"kimpo", x3::standard_wide::lit(ws))));
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
{
|
||||
BOOST_TEST((test("kimpo", "kimpo")));
|
||||
BOOST_TEST((test("kimpo", x3::standard::string("kimpo"))));
|
||||
|
||||
BOOST_TEST((test("x", x3::standard::string("x"))));
|
||||
BOOST_TEST((test(L"x", x3::standard_wide::string(L"x"))));
|
||||
|
||||
std::basic_string<char> s("kimpo");
|
||||
std::basic_string<wchar_t> ws(L"kimpo");
|
||||
BOOST_TEST((test("kimpo", s)));
|
||||
BOOST_TEST((test(L"kimpo", ws)));
|
||||
BOOST_TEST((test("kimpo", x3::standard::string(s))));
|
||||
BOOST_TEST((test(L"kimpo", x3::standard_wide::string(ws))));
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST((test(L"kimpo", L"kimpo")));
|
||||
BOOST_TEST((test(L"kimpo", x3::standard_wide::string(L"kimpo"))));
|
||||
BOOST_TEST((test(L"x", x3::standard_wide::string(L"x"))));
|
||||
}
|
||||
|
||||
{
|
||||
std::basic_string<char> s("kimpo");
|
||||
BOOST_TEST((test("kimpo", x3::standard::string(s))));
|
||||
|
||||
std::basic_string<wchar_t> ws(L"kimpo");
|
||||
BOOST_TEST((test(L"kimpo", x3::standard_wide::string(ws))));
|
||||
}
|
||||
|
||||
{
|
||||
// single-element fusion vector tests
|
||||
boost::fusion::vector<std::string> s;
|
||||
BOOST_TEST(test_attr("kimpo", x3::standard::string("kimpo"), s));
|
||||
BOOST_TEST(boost::fusion::at_c<0>(s) == "kimpo");
|
||||
}
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 Joel de Guzman
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
=============================================================================*/
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
|
||||
#include <string>
|
||||
#include "test.hpp"
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using spirit_test::test;
|
||||
using spirit_test::test_attr;
|
||||
using boost::spirit::x3::string;
|
||||
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(string("x"));
|
||||
|
||||
{
|
||||
BOOST_TEST((test("kimpo", "kimpo")));
|
||||
BOOST_TEST((test("kimpo", string("kimpo"))));
|
||||
|
||||
BOOST_TEST((test("x", string("x"))));
|
||||
BOOST_TEST((test(L"x", string(L"x"))));
|
||||
|
||||
std::basic_string<char> s("kimpo");
|
||||
std::basic_string<wchar_t> ws(L"kimpo");
|
||||
BOOST_TEST((test("kimpo", s)));
|
||||
BOOST_TEST((test(L"kimpo", ws)));
|
||||
BOOST_TEST((test("kimpo", string(s))));
|
||||
BOOST_TEST((test(L"kimpo", string(ws))));
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST((test(L"kimpo", L"kimpo")));
|
||||
BOOST_TEST((test(L"kimpo", string(L"kimpo"))));
|
||||
BOOST_TEST((test(L"x", string(L"x"))));
|
||||
}
|
||||
|
||||
{
|
||||
std::basic_string<char> s("kimpo");
|
||||
BOOST_TEST((test("kimpo", string(s))));
|
||||
|
||||
std::basic_string<wchar_t> ws(L"kimpo");
|
||||
BOOST_TEST((test(L"kimpo", string(ws))));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
BOOST_TEST((test(" kimpo", string("kimpo"), space)));
|
||||
BOOST_TEST((test(L" kimpo", string(L"kimpo"), space)));
|
||||
BOOST_TEST((test(" x", string("x"), space)));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
BOOST_TEST((test(" kimpo", string("kimpo"), space)));
|
||||
BOOST_TEST((test(L" kimpo", string(L"kimpo"), space)));
|
||||
BOOST_TEST((test(" x", string("x"), space)));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
std::string s;
|
||||
BOOST_TEST((test_attr("kimpo", string("kimpo"), s)));
|
||||
BOOST_TEST(s == "kimpo");
|
||||
s.clear();
|
||||
BOOST_TEST((test_attr("kimpo", string("kim") >> string("po"), s)));
|
||||
BOOST_TEST(s == "kimpo");
|
||||
s.clear();
|
||||
BOOST_TEST((test_attr(L"kimpo", string(L"kimpo"), s)));
|
||||
BOOST_TEST(s == "kimpo");
|
||||
s.clear();
|
||||
BOOST_TEST((test_attr("x", string("x"), s)));
|
||||
BOOST_TEST(s == "x");
|
||||
}
|
||||
|
||||
{ // single-element fusion vector tests
|
||||
boost::fusion::vector<std::string> s;
|
||||
BOOST_TEST(test_attr("kimpo", string("kimpo"), s));
|
||||
BOOST_TEST(boost::fusion::at_c<0>(s) == "kimpo");
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
=============================================================================*/
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include "test.hpp"
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using spirit_test::test;
|
||||
using spirit_test::test_attr;
|
||||
using boost::spirit::x3::lit;
|
||||
|
||||
{
|
||||
BOOST_TEST((test("kimpo", lit("kimpo"))));
|
||||
|
||||
std::basic_string<char> s("kimpo");
|
||||
std::basic_string<wchar_t> ws(L"kimpo");
|
||||
BOOST_TEST((test("kimpo", lit(s))));
|
||||
BOOST_TEST((test(L"kimpo", lit(ws))));
|
||||
}
|
||||
|
||||
{
|
||||
std::basic_string<char> s("kimpo");
|
||||
BOOST_TEST((test("kimpo", lit(s))));
|
||||
|
||||
std::basic_string<wchar_t> ws(L"kimpo");
|
||||
BOOST_TEST((test(L"kimpo", lit(ws))));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
BOOST_TEST((test(" kimpo", lit("kimpo"), space)));
|
||||
BOOST_TEST((test(L" kimpo", lit(L"kimpo"), space)));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::iso8859_1;
|
||||
BOOST_TEST((test(" kimpo", lit("kimpo"), space)));
|
||||
BOOST_TEST((test(L" kimpo", lit(L"kimpo"), space)));
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 Joel de Guzman
|
||||
http://spirit.sourceforge.net/
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -11,8 +11,7 @@
|
||||
#include <iostream>
|
||||
#include "test.hpp"
|
||||
|
||||
int
|
||||
main()
|
||||
int main()
|
||||
{
|
||||
using spirit_test::test;
|
||||
using spirit_test::test_attr;
|
||||
@@ -21,7 +20,7 @@ main()
|
||||
BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(no_case['x']);
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
using namespace boost::spirit::x3::standard;
|
||||
BOOST_TEST(test("x", no_case[char_]));
|
||||
BOOST_TEST(test("X", no_case[char_('x')]));
|
||||
BOOST_TEST(test("X", no_case[char_('X')]));
|
||||
@@ -35,7 +34,7 @@ main()
|
||||
BOOST_TEST(!test("z", no_case[char_('a', 'y')]));
|
||||
}
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
using namespace boost::spirit::x3::standard;
|
||||
BOOST_TEST(test("X", no_case['x']));
|
||||
BOOST_TEST(test("X", no_case['X']));
|
||||
BOOST_TEST(test("x", no_case['X']));
|
||||
@@ -45,24 +44,13 @@ main()
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::iso8859_1;
|
||||
using namespace boost::spirit::x3::standard;
|
||||
BOOST_TEST(test("X", no_case[char_("a-z")]));
|
||||
BOOST_TEST(!test("1", no_case[char_("a-z")]));
|
||||
}
|
||||
|
||||
{ // test extended ASCII characters
|
||||
using namespace boost::spirit::x3::iso8859_1;
|
||||
BOOST_TEST(test("\xC1", no_case[char_('\xE1')]));
|
||||
|
||||
BOOST_TEST(test("\xC9", no_case[char_("\xE5-\xEF")]));
|
||||
BOOST_TEST(!test("\xFF", no_case[char_("\xE5-\xEF")]));
|
||||
|
||||
BOOST_TEST(test("\xC1\xE1", no_case[lit("\xE1\xC1")]));
|
||||
BOOST_TEST(test("\xE1\xE1", no_case[no_case[lit("\xE1\xC1")]]));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
using namespace boost::spirit::x3::standard;
|
||||
BOOST_TEST(test("Bochi Bochi", no_case[lit("bochi bochi")]));
|
||||
BOOST_TEST(test("BOCHI BOCHI", no_case[lit("bochi bochi")]));
|
||||
BOOST_TEST(!test("Vavoo", no_case[lit("bochi bochi")]));
|
||||
@@ -70,40 +58,12 @@ main()
|
||||
|
||||
{
|
||||
// should work!
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
using namespace boost::spirit::x3::standard;
|
||||
BOOST_TEST(test("x", no_case[no_case[char_]]));
|
||||
BOOST_TEST(test("x", no_case[no_case[char_('x')]]));
|
||||
BOOST_TEST(test("yabadabadoo", no_case[no_case[lit("Yabadabadoo")]]));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
BOOST_TEST(test("X", no_case[alnum]));
|
||||
BOOST_TEST(test("6", no_case[alnum]));
|
||||
BOOST_TEST(!test(":", no_case[alnum]));
|
||||
|
||||
BOOST_TEST(test("X", no_case[lower]));
|
||||
BOOST_TEST(test("x", no_case[lower]));
|
||||
BOOST_TEST(test("X", no_case[upper]));
|
||||
BOOST_TEST(test("x", no_case[upper]));
|
||||
BOOST_TEST(!test(":", no_case[lower]));
|
||||
BOOST_TEST(!test(":", no_case[upper]));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::iso8859_1;
|
||||
BOOST_TEST(test("X", no_case[alnum]));
|
||||
BOOST_TEST(test("6", no_case[alnum]));
|
||||
BOOST_TEST(!test(":", no_case[alnum]));
|
||||
|
||||
BOOST_TEST(test("X", no_case[lower]));
|
||||
BOOST_TEST(test("x", no_case[lower]));
|
||||
BOOST_TEST(test("X", no_case[upper]));
|
||||
BOOST_TEST(test("x", no_case[upper]));
|
||||
BOOST_TEST(!test(":", no_case[lower]));
|
||||
BOOST_TEST(!test(":", no_case[upper]));
|
||||
}
|
||||
|
||||
{
|
||||
using namespace boost::spirit::x3::standard;
|
||||
BOOST_TEST(test("X", no_case[alnum]));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -21,16 +22,15 @@ private:
|
||||
char str[2];
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
int main()
|
||||
{
|
||||
using spirit_test::test;
|
||||
using spirit_test::test_attr;
|
||||
using boost::spirit::x3::symbols;
|
||||
using boost::spirit::x3::shared_symbols;
|
||||
using boost::spirit::x3::no_case;
|
||||
|
||||
{ // basics
|
||||
symbols<int> sym;
|
||||
shared_symbols<int> sym;
|
||||
|
||||
sym.add
|
||||
("Joel")
|
||||
@@ -52,7 +52,7 @@ main()
|
||||
BOOST_TEST((!test("XXX", sym)));
|
||||
|
||||
// test copy
|
||||
symbols<int> sym2;
|
||||
shared_symbols<int> sym2;
|
||||
sym2 = sym;
|
||||
BOOST_TEST((test("Joel", sym2)));
|
||||
BOOST_TEST((test("Ruby", sym2)));
|
||||
@@ -75,7 +75,7 @@ main()
|
||||
}
|
||||
|
||||
{ // comma syntax
|
||||
symbols<int> sym;
|
||||
shared_symbols<int> sym;
|
||||
sym += "Joel", "Ruby", "Tenji", "Tutit", "Kim", "Joey";
|
||||
|
||||
BOOST_TEST((test("Joel", sym)));
|
||||
@@ -93,9 +93,9 @@ main()
|
||||
}
|
||||
|
||||
{ // no-case handling
|
||||
using namespace boost::spirit::x3::ascii;
|
||||
using namespace boost::spirit::x3::standard;
|
||||
|
||||
symbols<int> sym;
|
||||
shared_symbols<int> sym;
|
||||
// NOTE: make sure all entries are in lower-case!!!
|
||||
sym = "joel", "ruby", "tenji", "tutit", "kim", "joey";
|
||||
|
||||
@@ -118,7 +118,7 @@ main()
|
||||
}
|
||||
|
||||
{ // attributes
|
||||
symbols<int> sym;
|
||||
shared_symbols<int> sym;
|
||||
|
||||
sym.add
|
||||
("Joel", 1)
|
||||
@@ -154,7 +154,7 @@ main()
|
||||
{ // actions
|
||||
using boost::spirit::x3::_attr;
|
||||
|
||||
symbols<int> sym;
|
||||
shared_symbols<int> sym;
|
||||
sym.add
|
||||
("Joel", 1)
|
||||
("Ruby", 2)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -9,34 +10,17 @@
|
||||
#include <iostream>
|
||||
#include "test.hpp"
|
||||
|
||||
// Custom string type with a C-style string conversion.
|
||||
struct custom_string_c
|
||||
{
|
||||
custom_string_c(char c) { str[0] = c; str[1] = '\0'; }
|
||||
|
||||
operator char*() { return str; }
|
||||
operator char const*() const { return str; }
|
||||
|
||||
private:
|
||||
char str[2];
|
||||
};
|
||||
|
||||
std::string get_str(char const* str)
|
||||
{
|
||||
return std::string(str);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
int main()
|
||||
{
|
||||
using spirit_test::test;
|
||||
using spirit_test::test_attr;
|
||||
using boost::spirit::x3::symbols;
|
||||
using boost::spirit::x3::shared_symbols;
|
||||
using boost::spirit::x3::rule;
|
||||
|
||||
{ // construction from symbol array
|
||||
char const* syms[] = {"Joel","Ruby","Tenji","Tutit","Kim","Joey"};
|
||||
symbols<int> sym(syms);
|
||||
{
|
||||
// construction from symbol array
|
||||
char const* syms[] = {"Joel", "Ruby", "Tenji", "Tutit", "Kim", "Joey"};
|
||||
shared_symbols<int> sym(syms);
|
||||
|
||||
BOOST_TEST((test("Joel", sym)));
|
||||
BOOST_TEST((test("Ruby", sym)));
|
||||
@@ -47,11 +31,12 @@ main()
|
||||
BOOST_TEST((!test("XXX", sym)));
|
||||
}
|
||||
|
||||
{ // construction from 2 arrays
|
||||
{
|
||||
// construction from 2 arrays
|
||||
|
||||
char const* syms[] = {"Joel","Ruby","Tenji","Tutit","Kim","Joey"};
|
||||
int data[] = {1,2,3,4,5,6};
|
||||
symbols<int> sym(syms, data);
|
||||
char const* syms[] = {"Joel", "Ruby", "Tenji", "Tutit", "Kim", "Joey"};
|
||||
int data[] = {1, 2, 3, 4, 5, 6};
|
||||
shared_symbols<int> sym(syms, data);
|
||||
|
||||
int i;
|
||||
BOOST_TEST((test_attr("Joel", sym, i)));
|
||||
@@ -69,8 +54,9 @@ main()
|
||||
BOOST_TEST((!test_attr("XXX", sym, i)));
|
||||
}
|
||||
|
||||
{ // allow std::string and other string types
|
||||
symbols<> sym;
|
||||
{
|
||||
// allow std::string and other string types
|
||||
shared_symbols<> sym;
|
||||
|
||||
// const and non-const std::string
|
||||
std::string a("abc");
|
||||
@@ -88,19 +74,12 @@ main()
|
||||
sym = arr;
|
||||
BOOST_TEST((test("a", sym)));
|
||||
BOOST_TEST((!test("b", sym)));
|
||||
|
||||
// const and non-const custom string type
|
||||
custom_string_c c('x');
|
||||
custom_string_c const cc('y');
|
||||
sym = c, cc;
|
||||
BOOST_TEST((test("x", sym)));
|
||||
BOOST_TEST((test("y", sym)));
|
||||
BOOST_TEST((!test("z", sym)));
|
||||
}
|
||||
|
||||
{ // find
|
||||
{
|
||||
// find
|
||||
|
||||
symbols<int> sym;
|
||||
shared_symbols<int> sym;
|
||||
sym.add("a", 1)("b", 2);
|
||||
|
||||
BOOST_TEST(!sym.find("c"));
|
||||
@@ -116,7 +95,7 @@ main()
|
||||
BOOST_TEST(sym.find("b") && *sym.find("b") == 2);
|
||||
BOOST_TEST(sym.find("c") && *sym.find("c") == 0);
|
||||
|
||||
symbols<int> const_sym(sym);
|
||||
shared_symbols<int> const_sym(sym);
|
||||
|
||||
BOOST_TEST(const_sym.find("a") && *const_sym.find("a") == 1);
|
||||
BOOST_TEST(const_sym.find("b") && *const_sym.find("b") == 2);
|
||||
@@ -132,20 +111,22 @@ main()
|
||||
BOOST_TEST(!sym.prefix_find(first, last) && first == str2);
|
||||
}
|
||||
|
||||
{ // name
|
||||
symbols <int> sym,sym2;
|
||||
{
|
||||
// name
|
||||
shared_symbols<int> sym,sym2;
|
||||
sym.name("test");
|
||||
BOOST_TEST(sym.name()=="test");
|
||||
sym2 = sym;
|
||||
BOOST_TEST(sym2.name()=="test");
|
||||
|
||||
symbols <int> sym3(sym);
|
||||
shared_symbols<int> sym3(sym);
|
||||
BOOST_TEST(sym3.name()=="test");
|
||||
}
|
||||
|
||||
{ // Substrings
|
||||
{
|
||||
// Substrings
|
||||
|
||||
symbols<int> sym;
|
||||
shared_symbols<int> sym;
|
||||
BOOST_TEST(sym.at("foo") == 0);
|
||||
sym.at("foo") = 1;
|
||||
BOOST_TEST(sym.at("foo") == 1);
|
||||
@@ -175,23 +156,22 @@ main()
|
||||
}
|
||||
|
||||
{
|
||||
// remove bug
|
||||
|
||||
std::string s;
|
||||
symbols<double> vars;
|
||||
shared_symbols<double> vars;
|
||||
|
||||
vars.add("l1", 12.0);
|
||||
vars.add("l2", 0.0);
|
||||
vars.remove("l2");
|
||||
vars.find("l1");
|
||||
(void)vars.find("l1");
|
||||
double* d = vars.find("l1");
|
||||
BOOST_TEST(d != 0);
|
||||
BOOST_TEST(d != nullptr);
|
||||
}
|
||||
|
||||
{ // test for proto problem with rvalue references (10-11-2011)
|
||||
symbols<int> sym;
|
||||
sym += get_str("Joel");
|
||||
sym += get_str("Ruby");
|
||||
{
|
||||
// test for proto problem with rvalue references (10-11-2011)
|
||||
shared_symbols<int> sym;
|
||||
sym += std::string("Joel");
|
||||
sym += std::string("Ruby");
|
||||
|
||||
BOOST_TEST((test("Joel", sym)));
|
||||
BOOST_TEST((test("Ruby", sym)));
|
||||
|
||||
@@ -1,30 +1,33 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2013 Carl Barron
|
||||
Copyright (c) 2015 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
=============================================================================*/
|
||||
|
||||
#define BOOST_SPIRIT_X3_DEBUG
|
||||
#define BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL 0
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/spirit/home/support/char_encoding/unicode.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include "test.hpp"
|
||||
|
||||
struct roman
|
||||
{
|
||||
boost::optional<int> a;
|
||||
boost::optional<int> b;
|
||||
boost::optional<int> c;
|
||||
std::optional<int> a;
|
||||
std::optional<int> b;
|
||||
std::optional<int> c;
|
||||
};
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(roman,
|
||||
@@ -33,30 +36,29 @@ BOOST_FUSION_ADAPT_STRUCT(roman,
|
||||
|
||||
int eval(roman const & c)
|
||||
{
|
||||
return c.a.get_value_or(0) + c.b.get_value_or(0) + c.c.get_value_or(0);
|
||||
return c.a.value_or(0) + c.b.value_or(0) + c.c.value_or(0);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
int main()
|
||||
{
|
||||
using spirit_test::test;
|
||||
using spirit_test::test_attr;
|
||||
using boost::spirit::x3::symbols;
|
||||
using boost::spirit::x3::shared_symbols;
|
||||
|
||||
{ // construction from initializer-list
|
||||
symbols<int> const ones =
|
||||
shared_symbols<int> const ones =
|
||||
{
|
||||
{"I", 1}, {"II", 2}, {"III", 3}, {"IV", 4},
|
||||
{"V", 5}, {"VI", 6}, {"VII", 7}, {"VIII", 8},
|
||||
{"IX", 9}
|
||||
};
|
||||
symbols<int> const tens =
|
||||
shared_symbols<int> const tens =
|
||||
{
|
||||
{"X", 10}, {"XX", 20}, {"XXX", 30}, {"XL", 40},
|
||||
{"L", 50}, {"LX", 60}, {"LXX", 70}, {"LXXX", 80},
|
||||
{"XC", 90}
|
||||
};
|
||||
symbols<int> const hundreds
|
||||
shared_symbols<int> const hundreds
|
||||
{
|
||||
{"C", 100}, {"CC", 200}, {"CCC", 300}, {"CD", 400},
|
||||
{"D", 500}, {"DC", 600}, {"DCC", 700}, {"DCCC", 800},
|
||||
@@ -71,13 +73,13 @@ main()
|
||||
}
|
||||
|
||||
{ // construction from initializer-list without attribute
|
||||
symbols<> foo = {"a1", "a2", "a3"};
|
||||
shared_symbols<> foo = {"a1", "a2", "a3"};
|
||||
|
||||
BOOST_TEST((test("a3", foo)));
|
||||
}
|
||||
|
||||
{ // assignment from initializer-list
|
||||
symbols<> foo;
|
||||
shared_symbols<> foo;
|
||||
foo = {"a1", "a2", "a3"};
|
||||
|
||||
BOOST_TEST((test("a3", foo)));
|
||||
@@ -85,7 +87,7 @@ main()
|
||||
|
||||
{ // unicode | construction from initializer-list
|
||||
using namespace boost::spirit;
|
||||
x3::symbols_parser<char_encoding::unicode, int> foo = {{U"a1", 1}, {U"a2", 2}, {U"a3", 3}};
|
||||
x3::shared_symbols_parser<char_encoding::unicode, int> foo = {{U"a1", 1}, {U"a2", 2}, {U"a3", 3}};
|
||||
|
||||
int r;
|
||||
BOOST_TEST((test_attr(U"a3", foo, r)));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2013 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -10,13 +11,16 @@
|
||||
#include <boost/spirit/home/x3/core/parse.hpp>
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/utility/string_view.hpp>
|
||||
|
||||
#include <string_view>
|
||||
#include <iostream>
|
||||
|
||||
namespace spirit_test
|
||||
{
|
||||
template <typename Char, typename Parser>
|
||||
bool test(Char const* in, Parser const& p, bool full_match = true)
|
||||
[[nodiscard]] bool test(
|
||||
Char const* in, Parser const& p, bool full_match = true
|
||||
)
|
||||
{
|
||||
Char const* last = in;
|
||||
while (*last)
|
||||
@@ -25,9 +29,11 @@ namespace spirit_test
|
||||
&& (!full_match || (in == last));
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser>
|
||||
bool test(boost::basic_string_view<Char, std::char_traits<Char>> in,
|
||||
Parser const& p, bool full_match = true)
|
||||
template <typename Char, typename CharTraits, typename Parser>
|
||||
[[nodiscard]] bool test(
|
||||
std::basic_string_view<Char, CharTraits> in,
|
||||
Parser const& p, bool full_match = true
|
||||
)
|
||||
{
|
||||
auto const last = in.end();
|
||||
auto pos = in.begin();
|
||||
@@ -36,8 +42,10 @@ namespace spirit_test
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser, typename Skipper>
|
||||
bool test(Char const* in, Parser const& p
|
||||
, Skipper const& s, bool full_match = true)
|
||||
[[nodiscard]] bool test(
|
||||
Char const* in, Parser const& p,
|
||||
Skipper const& s, bool full_match = true
|
||||
)
|
||||
{
|
||||
Char const* last = in;
|
||||
while (*last)
|
||||
@@ -47,7 +55,7 @@ namespace spirit_test
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser>
|
||||
bool test_failure(Char const* in, Parser const& p)
|
||||
[[nodiscard]] bool test_failure(Char const* in, Parser const& p)
|
||||
{
|
||||
Char const * const start = in;
|
||||
Char const* last = in;
|
||||
@@ -57,17 +65,20 @@ namespace spirit_test
|
||||
return !boost::spirit::x3::parse(in, last, p) && (in == start);
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser>
|
||||
bool test_failure(boost::basic_string_view<Char, std::char_traits<Char>> const in,
|
||||
Parser const& p)
|
||||
template <typename Char, typename CharTraits, typename Parser>
|
||||
[[nodiscard]] bool test_failure(
|
||||
std::basic_string_view<Char, CharTraits> const in, Parser const& p
|
||||
)
|
||||
{
|
||||
auto pos = in.begin();
|
||||
return !boost::spirit::x3::parse(pos, in.end(), p) && (pos == in.begin());
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser, typename Attr>
|
||||
bool test_attr(Char const* in, Parser const& p
|
||||
, Attr& attr, bool full_match = true)
|
||||
[[nodiscard]] bool test_attr(
|
||||
Char const* in, Parser const& p,
|
||||
Attr& attr, bool full_match = true
|
||||
)
|
||||
{
|
||||
Char const* last = in;
|
||||
while (*last)
|
||||
@@ -77,8 +88,10 @@ namespace spirit_test
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser, typename Attr, typename Skipper>
|
||||
bool test_attr(Char const* in, Parser const& p
|
||||
, Attr& attr, Skipper const& s, bool full_match = true)
|
||||
[[nodiscard]] bool test_attr(
|
||||
Char const* in, Parser const& p,
|
||||
Attr& attr, Skipper const& s, bool full_match = true
|
||||
)
|
||||
{
|
||||
Char const* last = in;
|
||||
while (*last)
|
||||
@@ -88,8 +101,10 @@ namespace spirit_test
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser>
|
||||
bool binary_test(Char const* in, std::size_t size, Parser const& p,
|
||||
bool full_match = true)
|
||||
[[nodiscard]] bool binary_test(
|
||||
Char const* in, std::size_t size, Parser const& p,
|
||||
bool full_match = true
|
||||
)
|
||||
{
|
||||
Char const* last = in + size;
|
||||
return boost::spirit::x3::parse(in, last, p)
|
||||
@@ -97,8 +112,10 @@ namespace spirit_test
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser, typename Skipper>
|
||||
bool binary_test(Char const* in, std::size_t size, Parser const& p,
|
||||
Skipper const& s, bool full_match = true)
|
||||
[[nodiscard]] bool binary_test(
|
||||
Char const* in, std::size_t size, Parser const& p,
|
||||
Skipper const& s, bool full_match = true
|
||||
)
|
||||
{
|
||||
Char const* last = in + size;
|
||||
return boost::spirit::x3::phrase_parse(in, last, p, s)
|
||||
@@ -106,8 +123,10 @@ namespace spirit_test
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser, typename Attr>
|
||||
bool binary_test_attr(Char const* in, std::size_t size, Parser const& p,
|
||||
Attr& attr, bool full_match = true)
|
||||
[[nodiscard]] bool binary_test_attr(
|
||||
Char const* in, std::size_t size, Parser const& p,
|
||||
Attr& attr, bool full_match = true
|
||||
)
|
||||
{
|
||||
Char const* last = in + size;
|
||||
return boost::spirit::x3::parse(in, last, p, attr)
|
||||
@@ -115,20 +134,21 @@ namespace spirit_test
|
||||
}
|
||||
|
||||
template <typename Char, typename Parser, typename Attr, typename Skipper>
|
||||
bool binary_test_attr(Char const* in, std::size_t size, Parser const& p,
|
||||
Attr& attr, Skipper const& s, bool full_match = true)
|
||||
[[nodiscard]] bool binary_test_attr(
|
||||
Char const* in, std::size_t size, Parser const& p,
|
||||
Attr& attr, Skipper const& s, bool full_match = true
|
||||
)
|
||||
{
|
||||
Char const* last = in + size;
|
||||
return boost::spirit::x3::phrase_parse(in, last, p, s, attr)
|
||||
&& (!full_match || (in == last));
|
||||
}
|
||||
|
||||
|
||||
template <typename... T>
|
||||
constexpr bool always_true(T&&...) { return true; }
|
||||
[[nodiscard]] constexpr bool always_true(T&&...) { return true; }
|
||||
|
||||
template <typename Parser>
|
||||
constexpr bool test_ctors(Parser const& p)
|
||||
[[nodiscard]] constexpr bool test_ctors(Parser const& p)
|
||||
{
|
||||
return always_true(
|
||||
static_cast<Parser>(static_cast<Parser&&>( // test move ctor
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
|
||||
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)
|
||||
@@ -8,7 +9,6 @@
|
||||
#include <boost/phoenix.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
@@ -22,10 +22,12 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// We place the data here. Each line comprises various fields
|
||||
typedef std::vector<std::string> ucd_line;
|
||||
typedef std::vector<ucd_line> ucd_vector;
|
||||
typedef std::vector<ucd_line>::iterator ucd_iterator;
|
||||
using ucd_line = std::vector<std::string>;
|
||||
using ucd_vector = std::vector<ucd_line>;
|
||||
using ucd_iterator = std::vector<ucd_line>::iterator;
|
||||
|
||||
// spirit and phoenix using declarations
|
||||
using boost::spirit::qi::parse;
|
||||
@@ -40,9 +42,9 @@ using boost::phoenix::push_back;
|
||||
using boost::phoenix::ref;
|
||||
|
||||
// basic unsigned types
|
||||
using boost::uint8_t;
|
||||
using boost::uint16_t;
|
||||
using boost::uint32_t;
|
||||
using std::uint8_t;
|
||||
using std::uint16_t;
|
||||
using std::uint32_t;
|
||||
|
||||
enum code_action
|
||||
{
|
||||
@@ -535,15 +537,16 @@ void print_head(Out& out)
|
||||
out
|
||||
<< "/*=============================================================================\n"
|
||||
<< " Copyright (c) 2001-2011 Joel de Guzman\n"
|
||||
<< " Copyright (c) 2025 Nana Sakisaka\n"
|
||||
<< "\n"
|
||||
<< " Distributed under the Boost Software License, Version 1.0. (See accompanying\n"
|
||||
<< " file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n"
|
||||
<< "\n"
|
||||
<< " AUTOGENERATED. DO NOT EDIT!!!\n"
|
||||
<< "==============================================================================*/\n"
|
||||
<< "#include <boost/cstdint.hpp>\n"
|
||||
<< "#include <cstdint>\n"
|
||||
<< "\n"
|
||||
<< "namespace boost { namespace spirit { namespace ucd { namespace detail\n"
|
||||
<< "namespace boost::spirit::x3::unicode::detail\n"
|
||||
<< "{"
|
||||
;
|
||||
}
|
||||
@@ -553,7 +556,7 @@ void print_tail(Out& out)
|
||||
{
|
||||
out
|
||||
<< "\n"
|
||||
<< "}}}} // namespace boost::spirit::unicode::detail\n"
|
||||
<< "} // boost::spirit::x3::unicode::detail\n"
|
||||
;
|
||||
}
|
||||
|
||||
@@ -561,10 +564,10 @@ char const* get_int_type_name(int size)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 1: return "::boost::uint8_t";
|
||||
case 2: return "::boost::uint16_t";
|
||||
case 4: return "::boost::uint32_t";
|
||||
case 5: return "::boost::uint64_t";
|
||||
case 1: return "std::uint8_t";
|
||||
case 2: return "std::uint16_t";
|
||||
case 4: return "std::uint32_t";
|
||||
case 5: return "std::uint64_t";
|
||||
default: BOOST_ASSERT(false); return 0; // invalid size
|
||||
};
|
||||
}
|
||||
@@ -588,7 +591,7 @@ void print_file(Out& out, Builder& builder, int field_width, char const* name)
|
||||
|
||||
out
|
||||
<< "\n"
|
||||
<< " static const ::boost::uint8_t " << name << "_stage1[] = {\n"
|
||||
<< " inline constexpr std::uint8_t " << name << "_stage1[] = {\n"
|
||||
<< "\n"
|
||||
;
|
||||
|
||||
@@ -600,7 +603,7 @@ void print_file(Out& out, Builder& builder, int field_width, char const* name)
|
||||
<< " };"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< " static const " << int_name << ' ' << name << "_stage2[] = {"
|
||||
<< " inline constexpr " << int_name << ' ' << name << "_stage2[] = {"
|
||||
;
|
||||
|
||||
int block_n = 0;
|
||||
@@ -621,9 +624,9 @@ void print_file(Out& out, Builder& builder, int field_width, char const* name)
|
||||
|
||||
out
|
||||
<< "\n"
|
||||
<< " inline " << int_name << ' ' << name << "_lookup(::boost::uint32_t ch)\n"
|
||||
<< " [[nodiscard]] constexpr " << int_name << ' ' << name << "_lookup(std::uint32_t ch) noexcept\n"
|
||||
<< " {\n"
|
||||
<< " ::boost::uint32_t block_offset = " << name << "_stage1[ch / " << block_size << "] * " << block_size << ";\n"
|
||||
<< " std::uint32_t block_offset = " << name << "_stage1[ch / " << block_size << "] * " << block_size << ";\n"
|
||||
<< " return " << name << "_stage2[block_offset + ch % " << block_size << "];\n"
|
||||
<< " }\n"
|
||||
;
|
||||
@@ -666,6 +669,4 @@ int main()
|
||||
builder.collect("UnicodeData.txt", 12, assign_code_value);
|
||||
print_file(out, builder, 6, "uppercase");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user