mirror of
https://github.com/boostorg/spirit.git
synced 2026-01-19 04:42:11 +00:00
Revert "Use concepts for attribute category overload resolution (#812)"
This reverts commit c64a9146fc.
This commit is contained in:
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@@ -228,7 +228,6 @@ jobs:
|
||||
key: ${{ steps.env-info.outputs.BOOST_RELEASE_VERSION_NAME }}-${{ matrix.os.name }}-${{ matrix.os.version }}-${{ matrix.compiler.toolset }}-${{ matrix.compiler.version }}-${{ matrix.cpp_version.name }}-${{ matrix.build_type.name }}
|
||||
path: |
|
||||
${{ steps.env-info.outputs.BOOST_ROOT }}
|
||||
!${{ steps.env-info.outputs.BOOST_ROOT }}/.git
|
||||
|
||||
- name: Clone upstream Boost libraries
|
||||
if: steps.cache-boost.outputs.cache-hit != 'true'
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
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)
|
||||
@@ -13,8 +12,6 @@
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/support/no_case.hpp>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -31,7 +28,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
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(*first, attr);
|
||||
++first;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
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 +7,8 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM)
|
||||
#define BOOST_SPIRIT_X3_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp>
|
||||
@@ -15,23 +16,14 @@
|
||||
#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/fusion/include/at_key.hpp>
|
||||
#include <boost/fusion/include/front.hpp>
|
||||
#include <boost/fusion/include/back.hpp>
|
||||
|
||||
// TODO: remove Boost.Variant usage
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <iterator> // for std::make_move_iterator
|
||||
|
||||
#include <ranges>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
template <typename Attribute, typename Value>
|
||||
struct saver_visitor;
|
||||
@@ -41,265 +33,277 @@ namespace boost::spirit::x3::detail
|
||||
struct save_to_assoc_attr
|
||||
{
|
||||
template <typename Value, typename Attribute>
|
||||
static constexpr void call(Key const&, Value&& value, Attribute& attr)
|
||||
noexcept(noexcept(traits::move_to(std::move(value), fusion::at_key<Key>(attr))))
|
||||
static void call(const Key, Value& value, Attribute& attr)
|
||||
{
|
||||
static_assert(std::is_rvalue_reference_v<Value&&>);
|
||||
traits::move_to(std::move(value), fusion::at_key<Key>(attr));
|
||||
traits::move_to(value, fusion::at_key<Key>(attr));
|
||||
}
|
||||
};
|
||||
|
||||
// save to associative fusion container where Key
|
||||
// is variant over possible keys
|
||||
template <typename... Ts>
|
||||
struct save_to_assoc_attr<variant<Ts...>>
|
||||
template <typename ...T>
|
||||
struct save_to_assoc_attr<variant<T...> >
|
||||
{
|
||||
typedef variant<T...> variant_t;
|
||||
|
||||
template <typename Value, typename Attribute>
|
||||
static constexpr void call(variant<Ts...> const& key, Value&& value, Attribute& attr)
|
||||
static void call(const variant_t key, Value& value, Attribute& attr)
|
||||
{
|
||||
static_assert(std::is_rvalue_reference_v<Value&&>);
|
||||
boost::apply_visitor(saver_visitor<Attribute, Value>(attr, std::move(value)), key);
|
||||
apply_visitor(saver_visitor<Attribute, Value>(attr, value), key);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Attribute, typename Value>
|
||||
struct saver_visitor : boost::static_visitor<void>
|
||||
struct saver_visitor : boost::static_visitor<void>
|
||||
{
|
||||
constexpr saver_visitor(Attribute& attr, Value&& value) noexcept
|
||||
: attr(attr)
|
||||
, value(std::move(value))
|
||||
{};
|
||||
saver_visitor(Attribute& attr, Value& value)
|
||||
: attr(attr), value(value) {};
|
||||
|
||||
Attribute& attr;
|
||||
Value&& value;
|
||||
Value& value;
|
||||
|
||||
template <typename Key>
|
||||
constexpr void operator()(Key const& key) const
|
||||
noexcept(noexcept(save_to_assoc_attr<Key>::call(key, std::move(value), attr)))
|
||||
void operator()(Key) const
|
||||
{
|
||||
save_to_assoc_attr<Key>::call(key, std::move(value), attr);
|
||||
save_to_assoc_attr<Key>::call(Key(), value,attr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, typename Container, typename Context>
|
||||
struct parser_accepts_container
|
||||
: traits::is_substitute<traits::attribute_of_t<Parser, Context>, Container>
|
||||
: traits::is_substitute<
|
||||
typename traits::attribute_of<Parser, Context>::type
|
||||
, Container
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Parser, typename Container, typename Context>
|
||||
constexpr bool parser_accepts_container_v = parser_accepts_container<Parser, Container, Context>::value;
|
||||
|
||||
template <typename Parser>
|
||||
struct parse_into_container_base_impl
|
||||
{
|
||||
private:
|
||||
|
||||
// Parser has attribute (synthesize; Attribute is a container)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires (!parser_accepts_container_v<Parser, Attribute, Context>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call_synthesize(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) // never noexcept (requires container insertion)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_x(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
|
||||
{
|
||||
// synthesized attribute needs to be value initialized
|
||||
using value_type = traits::container_value_t<Attribute>;
|
||||
value_type val; // default-initialize
|
||||
using value_type = typename traits::container_value<Attribute>::type;
|
||||
value_type val{};
|
||||
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, value_type>);
|
||||
if (!parser.parse(first, last, context, rcontext, val))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// push the parsed value into our attribute
|
||||
traits::push_back(attr, std::move(val));
|
||||
traits::push_back(attr, static_cast<value_type&&>(val));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parser has attribute (synthesize; Attribute is a container)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires parser_accepts_container_v<Parser, Attribute, Context>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call_synthesize(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(is_nothrow_parsable_v<Parser, It, Se, Context, RContext, Attribute>)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_x(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
|
||||
{
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, Attribute>);
|
||||
return parser.parse(first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
// Parser has attribute && it is NOT fusion sequence
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires
|
||||
traits::has_attribute_v<Parser, Context> &&
|
||||
(!fusion::traits::is_sequence<Attribute>::value)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
)
|
||||
// Parser has attribute (synthesize; Attribute is a container)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
static bool call_synthesize(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
// TODO: reduce call stack while keeping maintainability
|
||||
return parse_into_container_base_impl::call_synthesize(parser, first, last, context, rcontext, attr);
|
||||
typedef
|
||||
parser_accepts_container<Parser, Attribute, Context>
|
||||
parser_accepts_container;
|
||||
|
||||
return call_synthesize_x(parser, first, last, context, rcontext, attr
|
||||
, parser_accepts_container());
|
||||
}
|
||||
|
||||
// Parser has attribute && it is fusion sequence (NOT associative)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires
|
||||
traits::has_attribute_v<Parser, Context> &&
|
||||
fusion::traits::is_sequence<Attribute>::value &&
|
||||
(!fusion::traits::is_associative<Attribute>::value)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(noexcept(parse_into_container_base_impl::call_synthesize(parser, first, last, context, rcontext, fusion::front(attr))))
|
||||
// Parser has attribute (synthesize; Attribute is a single element fusion sequence)
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_into_fusion_seq(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::false_ /* is_associative */)
|
||||
{
|
||||
static_assert(traits::has_size_v<Attribute, 1>, "Expecting a single element fusion sequence");
|
||||
// TODO: reduce call stack while keeping maintainability
|
||||
return parse_into_container_base_impl::call_synthesize(parser, first, last, context, rcontext, fusion::front(attr));
|
||||
static_assert(traits::has_size<Attribute, 1>::value,
|
||||
"Expecting a single element fusion sequence");
|
||||
return call_synthesize(parser, first, last, context, rcontext,
|
||||
fusion::front(attr));
|
||||
}
|
||||
|
||||
// Parser has attribute && it is fusion sequence (associative)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires
|
||||
traits::has_attribute_v<Parser, Context> &&
|
||||
fusion::traits::is_sequence<Attribute>::value &&
|
||||
fusion::traits::is_associative<Attribute>::value
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) // never noexcept (requires container insertion)
|
||||
// Parser has attribute (synthesize; Attribute is fusion map sequence)
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_into_fusion_seq(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::true_ /*is_associative*/)
|
||||
{
|
||||
using attribute_type = traits::attribute_of_t<Parser, Context>;
|
||||
static_assert(traits::has_size_v<attribute_type, 2>, "To parse directly into fusion map, parser must produce 2 element attr");
|
||||
using attribute_type = typename traits::attribute_of<Parser, Context>::type;
|
||||
static_assert(traits::has_size<attribute_type, 2>::value,
|
||||
"To parse directly into fusion map parser must produce 2 element attr");
|
||||
|
||||
attribute_type attr_; // default-initialize
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, attribute_type>);
|
||||
// use type of first element of attribute as key
|
||||
using key = typename std::remove_reference<
|
||||
typename fusion::result_of::front<attribute_type>::type>::type;
|
||||
|
||||
attribute_type attr_;
|
||||
if (!parser.parse(first, last, context, rcontext, attr_))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use the type of first element of attribute as key
|
||||
using key = std::remove_reference_t<
|
||||
typename fusion::result_of::front<attribute_type>::type
|
||||
>;
|
||||
|
||||
save_to_assoc_attr<key>::call(std::move(fusion::front(attr_)), std::move(fusion::back(attr_)), attr);
|
||||
save_to_assoc_attr<key>::call(fusion::front(attr_), fusion::back(attr_), attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parser has no attribute (pass unused)
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires (!traits::has_attribute_v<Parser, Context>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& /* attr */
|
||||
) noexcept(is_nothrow_parsable_v<Parser, It, Se, Context, RContext, unused_type>)
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_dispatch_by_seq(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::true_ /*is_sequence*/)
|
||||
{
|
||||
return call_synthesize_into_fusion_seq(
|
||||
parser, first, last, context, rcontext, attr
|
||||
, fusion::traits::is_associative<Attribute>());
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call_synthesize_dispatch_by_seq(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::false_ /*is_sequence*/)
|
||||
{
|
||||
return call_synthesize(parser, first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
// Parser has attribute (synthesize)
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr, mpl::true_)
|
||||
{
|
||||
return call_synthesize_dispatch_by_seq(parser, first, last, context, rcontext, attr
|
||||
, fusion::traits::is_sequence<Attribute>());
|
||||
}
|
||||
|
||||
// Parser has no attribute (pass unused)
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& /* attr */, mpl::false_)
|
||||
{
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, unused_type>);
|
||||
return parser.parse(first, last, context, rcontext, unused);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
static bool call(Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
return call(parser, first, last, context, rcontext, attr
|
||||
, mpl::bool_<traits::has_attribute<Parser, Context>::value>());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, typename Context, typename RContext, typename Enable = void>
|
||||
struct parse_into_container_impl : parse_into_container_base_impl<Parser> {};
|
||||
|
||||
template <typename Parser, typename Iterator, typename Container, typename Context>
|
||||
struct parser_attr_is_substitute_for_container_value
|
||||
: traits::is_substitute<
|
||||
typename traits::pseudo_attribute<
|
||||
Context
|
||||
, typename traits::attribute_of<Parser, Context>::type
|
||||
, Iterator
|
||||
>::type
|
||||
, typename traits::container_value<Container>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Parser, typename Context, typename RContext>
|
||||
requires traits::handles_container_v<Parser, Context>
|
||||
struct parse_into_container_impl<Parser, Context, RContext>
|
||||
struct parse_into_container_impl<Parser, Context, RContext,
|
||||
typename enable_if<traits::handles_container<Parser, Context>>::type>
|
||||
{
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
static constexpr bool pass_attibute_as_is = std::disjunction_v<
|
||||
parser_accepts_container<Parser, Attribute, Context>,
|
||||
|
||||
std::negation<traits::is_substitute< // parser attribute is substitute for container value?
|
||||
traits::pseudo_attribute_t<
|
||||
Context,
|
||||
traits::attribute_of_t<Parser, Context>,
|
||||
It, Se
|
||||
>,
|
||||
traits::container_value_t<Attribute>
|
||||
>>
|
||||
>;
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
requires (!pass_attibute_as_is<It, Se, Attribute>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(noexcept(parse_into_container_base_impl<Parser>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
)))
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
|
||||
{
|
||||
return parse_into_container_base_impl<Parser>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
);
|
||||
parser, first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se>
|
||||
requires pass_attibute_as_is<It, Se, unused_type>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, unused_type
|
||||
) noexcept(is_nothrow_parsable_v<Parser, It, Se, Context, RContext, unused_type>)
|
||||
template <typename Iterator>
|
||||
static bool call(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, unused_type attr, mpl::true_)
|
||||
{
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, unused_type>);
|
||||
return parser.parse(first, last, context, rcontext, unused);
|
||||
return parser.parse(first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
requires pass_attibute_as_is<It, Se, Attribute>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) // never noexcept (requires container insertion)
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
|
||||
{
|
||||
static_assert(Parsable<Parser, It, Se, Context, RContext, Attribute>);
|
||||
if (traits::is_empty(attr))
|
||||
{
|
||||
return parser.parse(first, last, context, rcontext, attr);
|
||||
}
|
||||
Attribute rest;
|
||||
bool r = parser.parse(first, last, context, rcontext, rest);
|
||||
if (r)
|
||||
traits::append(attr, std::make_move_iterator(rest.begin()),
|
||||
std::make_move_iterator(rest.end()));
|
||||
return r;
|
||||
}
|
||||
|
||||
Attribute rest; // default-initialize
|
||||
if (!parser.parse(first, last, context, rcontext, rest))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
traits::append(
|
||||
attr,
|
||||
std::make_move_iterator(std::ranges::begin(rest)),
|
||||
std::make_move_iterator(std::ranges::end(rest))
|
||||
);
|
||||
return true;
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(Parser const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
typedef parser_accepts_container<
|
||||
Parser, Attribute, Context>
|
||||
parser_accepts_container;
|
||||
|
||||
typedef parser_attr_is_substitute_for_container_value<
|
||||
Parser, Iterator, Attribute, Context>
|
||||
parser_attr_is_substitute_for_container_value;
|
||||
|
||||
typedef mpl::or_<
|
||||
parser_accepts_container
|
||||
, mpl::not_<parser_attr_is_substitute_for_container_value>>
|
||||
pass_attibute_as_is;
|
||||
|
||||
return call(parser, first, last, context, rcontext, attr,
|
||||
pass_attibute_as_is());
|
||||
}
|
||||
};
|
||||
|
||||
template <
|
||||
typename Parser, std::forward_iterator It, std::sentinel_for<It> Se,
|
||||
typename Context, typename RContext, typename Attribute
|
||||
>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse_into_container(
|
||||
Parser const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(noexcept(parse_into_container_impl<Parser, Context, RContext>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
)))
|
||||
template <typename Parser, typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse_into_container(
|
||||
Parser const& parser
|
||||
, Iterator& first, Iterator const& last, Context const& context
|
||||
, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
return parse_into_container_impl<Parser, Context, RContext>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
);
|
||||
parser, first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace boost::spirit::x3
|
||||
Attribute& attr
|
||||
)
|
||||
{
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, unused_type, unused_type, Attribute>);
|
||||
static_assert(Parsable<Parser, It, Se, unused_type, unused_type, Attribute>);
|
||||
return as_parser(std::forward<Parser>(p)).parse(first, last, unused, unused, attr);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace boost::spirit::x3
|
||||
auto failure_ctx = x3::make_context<expectation_failure_tag>(expect_failure);
|
||||
using Context = decltype(failure_ctx);
|
||||
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
static_assert(Parsable<Parser, It, Se, Context, unused_type, Attribute>);
|
||||
|
||||
It first = std::ranges::begin(range);
|
||||
Se last = std::ranges::end(range);
|
||||
@@ -128,7 +128,7 @@ namespace boost::spirit::x3
|
||||
auto failure_ctx = x3::make_context<expectation_failure_tag>(res.expect_failure);
|
||||
using Context = decltype(failure_ctx);
|
||||
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
static_assert(Parsable<Parser, It, Se, Context, unused_type, Attribute>);
|
||||
|
||||
It first = std::ranges::begin(range);
|
||||
Se last = std::ranges::end(range);
|
||||
@@ -198,7 +198,7 @@ namespace boost::spirit::x3
|
||||
{
|
||||
auto skipper_ctx = x3::make_context<skipper_tag>(as_parser(std::forward<Skipper>(s)));
|
||||
using Context = decltype(skipper_ctx);
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
static_assert(Parsable<Parser, It, Se, Context, unused_type, Attribute>);
|
||||
|
||||
bool const ok = as_parser(std::forward<Parser>(p)).parse(first, last, skipper_ctx, unused, attr);
|
||||
if (post_skip == skip_flag::post_skip)
|
||||
@@ -290,7 +290,7 @@ namespace boost::spirit::x3
|
||||
auto ctx = x3::make_context<expectation_failure_tag>(expect_failure, skipper_ctx);
|
||||
|
||||
using Context = decltype(ctx);
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
static_assert(Parsable<Parser, It, Se, Context, unused_type, Attribute>);
|
||||
|
||||
It first = std::ranges::begin(range);
|
||||
Se last = std::ranges::end(range);
|
||||
@@ -332,7 +332,7 @@ namespace boost::spirit::x3
|
||||
auto ctx = x3::make_context<expectation_failure_tag>(res.expect_failure, skipper_ctx);
|
||||
|
||||
using Context = decltype(ctx);
|
||||
static_assert(Parsable<as_parser_plain_t<Parser>, It, Se, Context, unused_type, Attribute>);
|
||||
static_assert(Parsable<Parser, It, Se, Context, unused_type, Attribute>);
|
||||
|
||||
It first = std::ranges::begin(range);
|
||||
Se last = std::ranges::end(range);
|
||||
|
||||
@@ -363,17 +363,8 @@ namespace boost::spirit::x3
|
||||
typename RContext,
|
||||
typename Attribute
|
||||
>
|
||||
struct is_parsable
|
||||
{
|
||||
static_assert(X3Subject<Parser>);
|
||||
static_assert(!std::is_reference_v<It>);
|
||||
static_assert(std::forward_iterator<It>);
|
||||
static_assert(std::sentinel_for<Se, It>);
|
||||
static_assert(!std::is_reference_v<Context>);
|
||||
static_assert(!std::is_reference_v<RContext>);
|
||||
static_assert(!std::is_reference_v<Attribute>);
|
||||
|
||||
static constexpr bool value = requires(Parser const& p) // mutable parser use case is currently unknown
|
||||
struct is_parsable : std::bool_constant<
|
||||
requires(std::remove_cvref_t<as_parser_t<Parser>> const& p) // mutable parser use case is currently unknown
|
||||
{
|
||||
{
|
||||
p.parse(
|
||||
@@ -384,7 +375,15 @@ namespace boost::spirit::x3
|
||||
std::declval<Attribute&>() // attr
|
||||
)
|
||||
} -> std::convertible_to<bool>;
|
||||
};
|
||||
}
|
||||
> {
|
||||
static_assert(X3Subject<Parser>);
|
||||
static_assert(!std::is_reference_v<It>);
|
||||
static_assert(std::forward_iterator<It>);
|
||||
static_assert(std::sentinel_for<Se, It>);
|
||||
static_assert(!std::is_reference_v<Context>);
|
||||
static_assert(!std::is_reference_v<RContext>);
|
||||
static_assert(!std::is_reference_v<Attribute>);
|
||||
};
|
||||
|
||||
template <typename Parser, typename It, typename Se, typename Context, typename RContext, typename Attribute>
|
||||
@@ -403,17 +402,8 @@ namespace boost::spirit::x3
|
||||
typename RContext,
|
||||
typename Attribute
|
||||
>
|
||||
struct is_nothrow_parsable
|
||||
{
|
||||
static_assert(X3Subject<Parser>);
|
||||
static_assert(!std::is_reference_v<It>);
|
||||
static_assert(std::forward_iterator<It>);
|
||||
static_assert(std::sentinel_for<Se, It>);
|
||||
static_assert(!std::is_reference_v<Context>);
|
||||
static_assert(!std::is_reference_v<RContext>);
|
||||
static_assert(!std::is_reference_v<Attribute>);
|
||||
|
||||
static constexpr bool value = requires(Parser const& p) // mutable parser use case is currently unknown
|
||||
struct is_nothrow_parsable : std::bool_constant<
|
||||
requires(std::remove_cvref_t<as_parser_t<Parser>> const& p) // mutable parser use case is currently unknown
|
||||
{
|
||||
{
|
||||
p.parse(
|
||||
@@ -424,8 +414,8 @@ namespace boost::spirit::x3
|
||||
std::declval<Attribute&>() // attr
|
||||
)
|
||||
} noexcept -> std::convertible_to<bool>;
|
||||
};
|
||||
};
|
||||
}
|
||||
> {};
|
||||
|
||||
template <typename Parser, typename It, typename Se, typename Context, typename RContext, typename Attribute>
|
||||
constexpr bool is_nothrow_parsable_v = is_nothrow_parsable<Parser, It, Se, Context, RContext, Attribute>::value;
|
||||
@@ -449,7 +439,7 @@ namespace boost::spirit::x3
|
||||
template <typename Parser, class It, class Se>
|
||||
concept X3Parser =
|
||||
X3Subject<Parser> &&
|
||||
is_parsable_v<as_parser_plain_t<Parser>, It, Se, unused_type, unused_type, unused_type>;
|
||||
is_parsable_v<Parser, It, Se, unused_type, unused_type, unused_type>;
|
||||
|
||||
|
||||
// The runtime type info that can be obtained via `x3::what(p)`.
|
||||
|
||||
51
include/boost/spirit/home/x3/core/proxy.hpp
Normal file
51
include/boost/spirit/home/x3/core/proxy.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024 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_PROXY_FEBRUARY_1_2013_0211PM)
|
||||
#define BOOST_SPIRIT_X3_PROXY_FEBRUARY_1_2013_0211PM
|
||||
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject, typename Derived>
|
||||
struct proxy : unary_parser<Subject, Derived>
|
||||
{
|
||||
static bool const is_pass_through_unary = true;
|
||||
|
||||
constexpr proxy(Subject const& subject)
|
||||
: unary_parser<Subject, Derived>(subject) {}
|
||||
|
||||
// Overload this when appropriate. The proxy parser will pick up
|
||||
// the most derived overload.
|
||||
template <typename Iterator, typename Context
|
||||
, typename RuleContext, typename Attribute, typename Category>
|
||||
bool parse_subject(Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, Attribute& attr, Category) const
|
||||
{
|
||||
this->subject.parse(first, last, context, rcontext, attr);
|
||||
return !has_expectation_failure(context);
|
||||
}
|
||||
|
||||
// Main entry point.
|
||||
template <typename Iterator, typename Context
|
||||
, typename RuleContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RuleContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
return this->derived().parse_subject(first, last, context, rcontext, attr
|
||||
, typename traits::attribute_category<Attribute>::type());
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/transform_attribute.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -20,25 +19,18 @@ namespace boost::spirit::x3
|
||||
namespace detail
|
||||
{
|
||||
struct parser_id;
|
||||
} // detail
|
||||
}
|
||||
|
||||
template <typename Exposed, typename Transformed>
|
||||
requires std::is_assignable_v<Exposed&, Transformed&&>
|
||||
struct default_transform_attribute
|
||||
{
|
||||
using type = Transformed;
|
||||
typedef Transformed type;
|
||||
|
||||
static constexpr Transformed pre(Exposed&)
|
||||
noexcept(std::is_nothrow_default_constructible_v<Transformed>)
|
||||
{
|
||||
return Transformed{};
|
||||
}
|
||||
static Transformed pre(Exposed&) { return Transformed(); }
|
||||
|
||||
template <typename TransformedT>
|
||||
static constexpr void post(Exposed& val, TransformedT&& attribute)
|
||||
noexcept(noexcept(traits::move_to(std::forward<TransformedT>(attribute), val)))
|
||||
static void post(Exposed& val, Transformed&& attribute)
|
||||
{
|
||||
traits::move_to(std::forward<TransformedT>(attribute), val);
|
||||
traits::move_to(std::forward<Transformed>(attribute), val);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,58 +38,56 @@ namespace boost::spirit::x3
|
||||
template <typename Attribute>
|
||||
struct default_transform_attribute<Attribute, Attribute>
|
||||
{
|
||||
using type = Attribute&;
|
||||
static constexpr Attribute& pre(Attribute& val) noexcept { return val; }
|
||||
static constexpr void post(Attribute&, Attribute const&) noexcept {}
|
||||
typedef Attribute& type;
|
||||
static Attribute& pre(Attribute& val) { return val; }
|
||||
static void post(Attribute&, Attribute const&) {}
|
||||
};
|
||||
|
||||
// main specialization for x3
|
||||
template <typename Exposed, typename Transformed, typename Enable = void>
|
||||
requires std::is_assignable_v<Exposed&, Transformed&&>
|
||||
struct transform_attribute
|
||||
: default_transform_attribute<Exposed, Transformed> {};
|
||||
: default_transform_attribute<Exposed, Transformed> {};
|
||||
|
||||
// unused_type needs some special handling as well
|
||||
template <>
|
||||
struct transform_attribute<unused_type, unused_type>
|
||||
{
|
||||
using type = unused_type;
|
||||
static constexpr unused_type pre(unused_type) noexcept { return unused; }
|
||||
static constexpr void post(unused_type, unused_type) noexcept {}
|
||||
typedef unused_type type;
|
||||
static unused_type pre(unused_type) { return unused; }
|
||||
static void post(unused_type, unused_type) {}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct transform_attribute<unused_type const, unused_type>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct transform_attribute<unused_type, Attribute>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct transform_attribute<unused_type const, Attribute>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct transform_attribute<Attribute, unused_type>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct transform_attribute<Attribute const, unused_type>
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
|
||||
: transform_attribute<unused_type, unused_type> {};
|
||||
} // boost::spirit::x3
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost::spirit::x3::traits
|
||||
{
|
||||
template <typename Exposed, typename Transformed>
|
||||
requires std::is_assignable_v<Exposed&, Transformed&&>
|
||||
struct transform_attribute<Exposed, Transformed, x3::detail::parser_id>
|
||||
: x3::transform_attribute<Exposed, Transformed>
|
||||
: x3::transform_attribute<Exposed, Transformed>
|
||||
{
|
||||
static_assert(!std::is_reference_v<Exposed>, "Exposed cannot be a reference type");
|
||||
static_assert(!std::is_reference_v<Transformed>, "Transformed cannot be a reference type");
|
||||
static_assert(!std::is_reference<Exposed>::value,
|
||||
"Exposed cannot be a reference type");
|
||||
static_assert(!std::is_reference<Transformed>::value,
|
||||
"Transformed cannot be a reference type");
|
||||
};
|
||||
} // boost::spirit::x3::traits
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
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)
|
||||
@@ -15,42 +14,42 @@
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/variant_has_substitute.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/variant_find_substitute.hpp>
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
#include <boost/fusion/include/front.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Left, typename Right>
|
||||
struct alternative;
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
struct pass_variant_unused
|
||||
{
|
||||
using type = unused_type;
|
||||
typedef unused_type type;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] static constexpr unused_type
|
||||
call(T&) noexcept
|
||||
static unused_type
|
||||
call(T&)
|
||||
{
|
||||
return unused_type{};
|
||||
return unused_type();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Attribute>
|
||||
struct pass_variant_used
|
||||
{
|
||||
using type = Attribute&;
|
||||
typedef Attribute& type;
|
||||
|
||||
[[nodiscard]] static constexpr Attribute&
|
||||
call(Attribute& v) noexcept
|
||||
static Attribute&
|
||||
call(Attribute& v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
@@ -59,44 +58,56 @@ namespace boost::spirit::x3::detail
|
||||
template <>
|
||||
struct pass_variant_used<unused_type> : pass_variant_unused {};
|
||||
|
||||
template <typename Parser, typename Attribute, typename Context, typename Enable = void>
|
||||
template <typename Parser, typename Attribute, typename Context
|
||||
, typename Enable = void>
|
||||
struct pass_parser_attribute
|
||||
{
|
||||
using attribute_type = traits::attribute_of_t<Parser, Context>;
|
||||
using substitute_type = traits::variant_find_substitute_t<Attribute, attribute_type>;
|
||||
typedef typename
|
||||
traits::attribute_of<Parser, Context>::type
|
||||
attribute_type;
|
||||
typedef typename
|
||||
traits::variant_find_substitute<Attribute, attribute_type>::type
|
||||
substitute_type;
|
||||
|
||||
using type = std::conditional_t<
|
||||
std::is_same_v<Attribute, substitute_type>,
|
||||
Attribute&,
|
||||
substitute_type
|
||||
>;
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
is_same<Attribute, substitute_type>
|
||||
, Attribute&
|
||||
, substitute_type
|
||||
>::type
|
||||
type;
|
||||
|
||||
template <typename Attribute_>
|
||||
requires std::is_same_v<Attribute_, std::remove_reference_t<type>>
|
||||
[[nodiscard]] static constexpr Attribute_&
|
||||
call(Attribute_& attribute) noexcept
|
||||
static Attribute_&
|
||||
call(Attribute_& attribute, mpl::true_)
|
||||
{
|
||||
return attribute;
|
||||
}
|
||||
|
||||
template <typename Attribute_>
|
||||
requires (!std::is_same_v<Attribute_, std::remove_reference_t<type>>)
|
||||
[[nodiscard]] static type
|
||||
call(Attribute_&)
|
||||
noexcept(std::is_nothrow_default_constructible_v<type>)
|
||||
static type
|
||||
call(Attribute_&, mpl::false_)
|
||||
{
|
||||
return type{};
|
||||
return type();
|
||||
}
|
||||
|
||||
template <typename Attribute_>
|
||||
static type
|
||||
call(Attribute_& attribute)
|
||||
{
|
||||
return call(attribute, is_same<Attribute_, typename remove_reference<type>::type>());
|
||||
}
|
||||
};
|
||||
|
||||
// Pass non-variant attributes as-is
|
||||
template <typename Parser, typename Attribute, typename Context, typename Enable = void>
|
||||
template <typename Parser, typename Attribute, typename Context
|
||||
, typename Enable = void>
|
||||
struct pass_non_variant_attribute
|
||||
{
|
||||
using type = Attribute&;
|
||||
typedef Attribute& type;
|
||||
|
||||
[[nodiscard]] constexpr static Attribute&
|
||||
call(Attribute& attribute) noexcept
|
||||
static Attribute&
|
||||
call(Attribute& attribute)
|
||||
{
|
||||
return attribute;
|
||||
}
|
||||
@@ -104,110 +115,80 @@ namespace boost::spirit::x3::detail
|
||||
|
||||
// Unwrap single element sequences
|
||||
template <typename Parser, typename Attribute, typename Context>
|
||||
requires traits::is_size_one_sequence_v<Attribute>
|
||||
struct pass_non_variant_attribute<Parser, Attribute, Context>
|
||||
struct pass_non_variant_attribute<Parser, Attribute, Context,
|
||||
typename enable_if<traits::is_size_one_sequence<Attribute>>::type>
|
||||
{
|
||||
using attr_type = typename std::remove_reference_t<
|
||||
typename fusion::result_of::front<Attribute>::type
|
||||
>;
|
||||
using pass = pass_parser_attribute<Parser, attr_type, Context>;
|
||||
using type = typename pass::type;
|
||||
typedef typename remove_reference<
|
||||
typename fusion::result_of::front<Attribute>::type>::type
|
||||
attr_type;
|
||||
|
||||
typedef pass_parser_attribute<Parser, attr_type, Context> pass;
|
||||
typedef typename pass::type type;
|
||||
|
||||
template <typename Attribute_>
|
||||
[[nodiscard]] static constexpr type
|
||||
static type
|
||||
call(Attribute_& attr)
|
||||
noexcept(noexcept(pass::call(fusion::front(attr))))
|
||||
{
|
||||
return pass::call(fusion::front(attr));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, typename Attribute, typename Context>
|
||||
requires (!traits::is_variant_v<Attribute>)
|
||||
struct pass_parser_attribute<Parser, Attribute, Context>
|
||||
struct pass_parser_attribute<Parser, Attribute, Context,
|
||||
typename enable_if_c<(!traits::is_variant<Attribute>::value)>::type>
|
||||
: pass_non_variant_attribute<Parser, Attribute, Context>
|
||||
{};
|
||||
|
||||
template <typename Parser, typename Context>
|
||||
struct pass_parser_attribute<Parser, unused_type, Context>
|
||||
: pass_variant_unused
|
||||
{};
|
||||
: pass_variant_unused {};
|
||||
|
||||
template <typename Parser, typename Attribute, typename Context>
|
||||
struct pass_variant_attribute
|
||||
: std::conditional_t<
|
||||
traits::has_attribute_v<Parser, Context>,
|
||||
pass_parser_attribute<Parser, Attribute, Context>,
|
||||
pass_variant_unused
|
||||
>
|
||||
{};
|
||||
struct pass_variant_attribute :
|
||||
mpl::if_c<traits::has_attribute<Parser, Context>::value
|
||||
, pass_parser_attribute<Parser, Attribute, Context>
|
||||
, pass_variant_unused>::type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename L, typename R, typename Attribute, typename Context>
|
||||
struct pass_variant_attribute<alternative<L, R>, Attribute, Context>
|
||||
: std::conditional_t<
|
||||
traits::has_attribute_v<alternative<L, R>, Context>,
|
||||
pass_variant_used<Attribute>,
|
||||
pass_variant_unused
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Parser, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Attribute>
|
||||
using parse_alternative_pseudo_t = traits::pseudo_attribute<
|
||||
Context, typename pass_variant_attribute<Parser, Attribute, Context>::type, It, Se
|
||||
>;
|
||||
|
||||
template <typename Parser, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Attribute>
|
||||
constexpr bool is_reference_pseudo_type = std::is_reference_v<typename parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::type>;
|
||||
|
||||
template <typename Parser, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires is_reference_pseudo_type<Parser, It, Se, Context, Attribute>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse_alternative(
|
||||
Parser const& p, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attribute
|
||||
) noexcept(
|
||||
noexcept(parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::call(
|
||||
first, last, pass_variant_attribute<Parser, Attribute, Context>::call(attribute)
|
||||
)) &&
|
||||
is_nothrow_parsable_v<
|
||||
Parser, It, Se, Context, RContext,
|
||||
std::remove_reference_t<typename parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::type>
|
||||
>
|
||||
)
|
||||
struct pass_variant_attribute<alternative<L, R>, Attribute, Context> :
|
||||
mpl::if_c<traits::has_attribute<alternative<L, R>, Context>::value
|
||||
, pass_variant_used<Attribute>
|
||||
, pass_variant_unused>::type
|
||||
{
|
||||
using pass = pass_variant_attribute<Parser, Attribute, Context>;
|
||||
using pseudo = traits::pseudo_attribute<Context, typename pass::type, It, Se>;
|
||||
typename pseudo::type attr_ = pseudo::call(first, last, pass::call(attribute));
|
||||
return p.parse(first, last, context, rcontext, attr_);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
|
||||
requires (!is_reference_pseudo_type<Parser, It, Se, Context, Attribute>)
|
||||
[[nodiscard]] constexpr bool
|
||||
parse_alternative(
|
||||
Parser const& p, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attribute
|
||||
) noexcept(
|
||||
noexcept(parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::call(
|
||||
first, last, pass_variant_attribute<Parser, Attribute, Context>::call(attribute)
|
||||
)) &&
|
||||
is_nothrow_parsable_v<
|
||||
Parser, It, Se, Context, RContext,
|
||||
std::remove_reference_t<typename parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::type>
|
||||
> &&
|
||||
noexcept(traits::move_to(
|
||||
std::declval<typename parse_alternative_pseudo_t<Parser, It, Se, Context, Attribute>::type&&>(),
|
||||
attribute
|
||||
))
|
||||
)
|
||||
template <bool Condition>
|
||||
struct move_if
|
||||
{
|
||||
using pass = pass_variant_attribute<Parser, Attribute, Context>;
|
||||
using pseudo = traits::pseudo_attribute<Context, typename pass::type, It, Se>;
|
||||
template<typename T1, typename T2>
|
||||
static void call(T1& /* attr_ */, T2& /* attr */) {}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct move_if<true>
|
||||
{
|
||||
template<typename T1, typename T2>
|
||||
static void call(T1& attr_, T2& attribute)
|
||||
{
|
||||
traits::move_to(attr_, attribute);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Parser, typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse_alternative(Parser const& p, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attribute)
|
||||
{
|
||||
using pass = detail::pass_variant_attribute<Parser, Attribute, Context>;
|
||||
using pseudo = traits::pseudo_attribute<Context, typename pass::type, Iterator>;
|
||||
|
||||
typename pseudo::type attr_ = pseudo::call(first, last, pass::call(attribute));
|
||||
|
||||
if (p.parse(first, last, context, rcontext, attr_))
|
||||
{
|
||||
traits::move_to(std::move(attr_), attribute);
|
||||
move_if<!std::is_reference<decltype(attr_)>::value>::call(attr_, attribute);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -216,14 +197,14 @@ namespace boost::spirit::x3::detail
|
||||
template <typename Subject>
|
||||
struct alternative_helper : unary_parser<Subject, alternative_helper<Subject>>
|
||||
{
|
||||
static constexpr bool is_pass_through_unary = true;
|
||||
static bool const is_pass_through_unary = true;
|
||||
|
||||
using unary_parser<Subject, alternative_helper<Subject>>::unary_parser;
|
||||
|
||||
template <typename Iterator, typename Context, typename RContext, typename Attribute>
|
||||
[[nodiscard]] constexpr bool parse(
|
||||
Iterator& first, Iterator const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const noexcept(noexcept(detail::parse_alternative(this->subject, first, last, context, rcontext, attr)))
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
{
|
||||
return detail::parse_alternative(this->subject, first, last, context, rcontext, attr);
|
||||
}
|
||||
@@ -232,34 +213,39 @@ namespace boost::spirit::x3::detail
|
||||
template <typename Left, typename Right, typename Context, typename RContext>
|
||||
struct parse_into_container_impl<alternative<Left, Right>, Context, RContext>
|
||||
{
|
||||
using parser_type = alternative<Left, Right>;
|
||||
typedef alternative<Left, Right> parser_type;
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
requires traits::is_variant_v<traits::container_value_t<Attribute>>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
parser_type const& parser,
|
||||
Iterator& first, Iterator const& last, Context const& context, RContext& rcontext, Attribute& attribute
|
||||
)
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attribute, mpl::false_)
|
||||
{
|
||||
return detail::parse_into_container(parser.left, first, last, context, rcontext, attribute)
|
||||
|| detail::parse_into_container(parser.right, first, last, context, rcontext, attribute);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attribute, mpl::true_)
|
||||
{
|
||||
return detail::parse_into_container(alternative_helper<Left>{parser.left}, first, last, context, rcontext, attribute)
|
||||
|| detail::parse_into_container(alternative_helper<Right>{parser.right}, first, last, context, rcontext, attribute);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
requires (!traits::is_variant_v<traits::container_value_t<Attribute>>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
parser_type const& parser,
|
||||
Iterator& first, Iterator const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attribute
|
||||
)
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attribute)
|
||||
{
|
||||
return detail::parse_into_container(parser.left, first, last, context, rcontext, attribute)
|
||||
|| detail::parse_into_container(parser.right, first, last, context, rcontext, attribute);
|
||||
return call(parser, first, last, context, rcontext, attribute,
|
||||
typename traits::is_variant<typename traits::container_value<Attribute>::type>::type{});
|
||||
}
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
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)
|
||||
@@ -26,15 +25,18 @@
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
#include <iterator> // for std::make_move_iterator
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Left, typename Right>
|
||||
struct sequence;
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::detail
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
template <typename Parser, typename Context, typename Enable = void>
|
||||
struct sequence_size
|
||||
@@ -356,62 +358,62 @@ namespace boost::spirit::x3::detail
|
||||
template <typename Left, typename Right, typename Context, typename RContext>
|
||||
struct parse_into_container_impl<sequence<Left, Right>, Context, RContext>
|
||||
{
|
||||
using parser_type = sequence<Left, Right>;
|
||||
typedef sequence<Left, Right> parser_type;
|
||||
|
||||
template <typename Attribute>
|
||||
static constexpr bool is_container_substitute = traits::is_substitute_v<
|
||||
traits::attribute_of_t<parser_type, Context>,
|
||||
traits::container_value_t<Attribute>
|
||||
>;
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
requires is_container_substitute<Attribute>
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
parser_type const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) noexcept(noexcept(parse_into_container_base_impl<parser_type>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
)))
|
||||
{
|
||||
return parse_into_container_base_impl<parser_type>::call(
|
||||
parser, first, last, context, rcontext, attr
|
||||
);
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
|
||||
requires (!is_container_substitute<Attribute>)
|
||||
[[nodiscard]] static constexpr bool
|
||||
call(
|
||||
parser_type const& parser, It& first, Se const& last,
|
||||
Context const& context, RContext& rcontext, Attribute& attr
|
||||
) // never noexcept (requires container insertion)
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
|
||||
{
|
||||
// inform user what went wrong if we jumped here in attempt to
|
||||
// parse incompatible sequence into fusion::map
|
||||
static_assert(
|
||||
!std::is_same_v<traits::attribute_category_t<Attribute>, traits::associative_attribute>,
|
||||
"To parse directly into fusion::map sequence must produce tuple attribute "
|
||||
"where type of first element is existing key in fusion::map and second element "
|
||||
"is value to be stored under that key"
|
||||
);
|
||||
static_assert(!is_same< typename traits::attribute_category<Attribute>::type,
|
||||
traits::associative_attribute>::value,
|
||||
"To parse directly into fusion::map sequence must produce tuple attribute "
|
||||
"where type of first element is existing key in fusion::map and second element "
|
||||
"is value to be stored under that key");
|
||||
|
||||
Attribute attr_{};
|
||||
if (!detail::parse_sequence(
|
||||
parser, first, last, context, rcontext, attr_, traits::container_attribute()
|
||||
))
|
||||
if (!parse_sequence(parser
|
||||
, first, last, context, rcontext, attr_, traits::container_attribute()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
traits::append(
|
||||
attr,
|
||||
std::make_move_iterator(traits::begin(attr_)),
|
||||
std::make_move_iterator(traits::end(attr_))
|
||||
);
|
||||
traits::append(attr, std::make_move_iterator(traits::begin(attr_)),
|
||||
std::make_move_iterator(traits::end(attr_)));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
|
||||
{
|
||||
return parse_into_container_base_impl<parser_type>::call(
|
||||
parser, first, last, context, rcontext, attr);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Attribute>
|
||||
static bool call(
|
||||
parser_type const& parser
|
||||
, Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr)
|
||||
{
|
||||
typedef typename
|
||||
traits::attribute_of<parser_type, Context>::type
|
||||
attribute_type;
|
||||
|
||||
typedef typename
|
||||
traits::container_value<Attribute>::type
|
||||
value_type;
|
||||
|
||||
return call(parser, first, last, context, rcontext, attr
|
||||
, typename traits::is_substitute<attribute_type, value_type>::type());
|
||||
}
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::detail
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2017 wanghan02
|
||||
Copyright (c) 2024-2025 Nana Sakisaka
|
||||
Copyright (c) 2024 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,7 +10,7 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_OPTIONAL_MARCH_23_2007_1117PM)
|
||||
#define BOOST_SPIRIT_X3_OPTIONAL_MARCH_23_2007_1117PM
|
||||
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/core/proxy.hpp>
|
||||
#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
|
||||
#include <boost/spirit/home/x3/support/expectation.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
|
||||
@@ -18,101 +18,72 @@
|
||||
#include <boost/spirit/home/x3/support/traits/optional_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename Subject>
|
||||
struct optional : unary_parser<Subject, optional<Subject>>
|
||||
struct optional : proxy<Subject, optional<Subject>>
|
||||
{
|
||||
using base_type = unary_parser<Subject, optional<Subject>>;
|
||||
static constexpr bool is_pass_through_unary = false;
|
||||
static constexpr bool handles_container = true;
|
||||
typedef proxy<Subject, optional<Subject>> base_type;
|
||||
static bool const is_pass_through_unary = false;
|
||||
static bool const handles_container = true;
|
||||
|
||||
template <typename SubjectT>
|
||||
requires std::is_constructible_v<Subject, SubjectT>
|
||||
constexpr optional(SubjectT&& subject)
|
||||
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
|
||||
: base_type(std::forward<SubjectT>(subject))
|
||||
{}
|
||||
constexpr optional(Subject const& subject)
|
||||
: base_type(subject) {}
|
||||
|
||||
// catch-all overload
|
||||
template <
|
||||
std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext,
|
||||
typename Attribute // unconstrained
|
||||
>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(
|
||||
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
|
||||
) const
|
||||
noexcept(is_nothrow_parsable_v<Subject, It, Se, Context, RContext, Attribute>)
|
||||
using base_type::parse_subject;
|
||||
|
||||
// Attribute is a container
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse_subject(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr
|
||||
, traits::container_attribute) const
|
||||
{
|
||||
static_assert(Parsable<Subject, It, Se, Context, RContext, Attribute>);
|
||||
|
||||
// discard [[nodiscard]]
|
||||
(void)this->subject.parse(first, last, context, rcontext, attr);
|
||||
return !x3::has_expectation_failure(context);
|
||||
detail::parse_into_container(
|
||||
this->subject, first, last, context, rcontext, attr);
|
||||
return !has_expectation_failure(context);
|
||||
}
|
||||
|
||||
// container attribute
|
||||
template <
|
||||
std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext,
|
||||
traits::CategorizedAttr<traits::container_attribute> Attribute
|
||||
>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
noexcept(noexcept(detail::parse_into_container(this->subject, first, last, context, rcontext, attr)))
|
||||
// Attribute is an optional
|
||||
template <typename Iterator, typename Context
|
||||
, typename RContext, typename Attribute>
|
||||
bool parse_subject(Iterator& first, Iterator const& last
|
||||
, Context const& context, RContext& rcontext, Attribute& attr
|
||||
, traits::optional_attribute) const
|
||||
{
|
||||
// discard [[nodiscard]]
|
||||
(void)detail::parse_into_container(this->subject, first, last, context, rcontext, attr);
|
||||
return !x3::has_expectation_failure(context);
|
||||
}
|
||||
typedef typename
|
||||
x3::traits::optional_value<Attribute>::type
|
||||
value_type;
|
||||
|
||||
// optional attribute
|
||||
template <
|
||||
std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext,
|
||||
traits::CategorizedAttr<traits::optional_attribute> Attribute
|
||||
>
|
||||
[[nodiscard]] constexpr bool
|
||||
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
|
||||
noexcept(
|
||||
std::is_nothrow_default_constructible_v<x3::traits::optional_value_t<Attribute>> &&
|
||||
is_nothrow_parsable_v<Subject, It, Se, Context, RContext, x3::traits::optional_value_t<Attribute>> &&
|
||||
noexcept(x3::traits::move_to(std::declval<x3::traits::optional_value_t<Attribute>&&>(), attr))
|
||||
)
|
||||
{
|
||||
using value_type = x3::traits::optional_value_t<Attribute>;
|
||||
value_type val; // default-initialize
|
||||
// create a local value
|
||||
value_type val{};
|
||||
|
||||
static_assert(Parsable<Subject, It, Se, Context, RContext, value_type>);
|
||||
if (this->subject.parse(first, last, context, rcontext, val))
|
||||
{
|
||||
// assign the parsed value into our attribute
|
||||
x3::traits::move_to(std::move(val), attr);
|
||||
return true;
|
||||
}
|
||||
x3::traits::move_to(val, attr);
|
||||
|
||||
return !x3::has_expectation_failure(context);
|
||||
} else {
|
||||
return !has_expectation_failure(context);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <X3Subject Subject>
|
||||
[[nodiscard]] constexpr optional<as_parser_plain_t<Subject>>
|
||||
operator-(Subject&& subject)
|
||||
noexcept(is_parser_nothrow_constructible_v<optional<as_parser_plain_t<Subject>>, Subject>)
|
||||
template <typename Subject>
|
||||
constexpr optional<typename extension::as_parser<Subject>::value_type>
|
||||
operator-(Subject const& subject)
|
||||
{
|
||||
return { as_parser(std::forward<Subject>(subject)) };
|
||||
return { as_parser(subject) };
|
||||
}
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Subject, typename Context>
|
||||
struct attribute_of<x3::optional<Subject>, Context>
|
||||
: build_optional<attribute_of_t<Subject, Context>>
|
||||
{};
|
||||
} // boost::spirit::x3::traits
|
||||
: build_optional<
|
||||
typename attribute_of<Subject, Context>::type> {};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
Copyright (c) 2011 Jan Frederick Eick
|
||||
Copyright (c) 2011 Christopher Jefferson
|
||||
Copyright (c) 2006 Stephen Nutt
|
||||
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)
|
||||
@@ -343,7 +342,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
|
||||
if (count + leading_zeros >= MinDigits)
|
||||
{
|
||||
traits::move_to(std::move(val), attr);
|
||||
traits::move_to(val, attr);
|
||||
first = it;
|
||||
return true;
|
||||
}
|
||||
@@ -445,7 +444,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
if (count == 0) // must have at least one digit
|
||||
return false;
|
||||
traits::move_to(std::move(val), attr);
|
||||
traits::move_to(val, attr);
|
||||
first = it;
|
||||
return true;
|
||||
}
|
||||
@@ -459,7 +458,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
, SPIRIT_NUMERIC_INNER_LOOP, _)
|
||||
}
|
||||
|
||||
traits::move_to(std::move(val), attr);
|
||||
traits::move_to(val, attr);
|
||||
first = it;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2011 Jan Frederick Eick
|
||||
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)
|
||||
@@ -78,7 +77,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
T attr;
|
||||
if (call(first, last, attr))
|
||||
{
|
||||
traits::move_to(std::move(attr), attr_);
|
||||
traits::move_to(attr, attr_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -132,7 +131,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
T attr;
|
||||
if (call(first, last, attr))
|
||||
{
|
||||
traits::move_to(std::move(attr), attr_);
|
||||
traits::move_to(attr, attr_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -8,22 +8,22 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ATTRIBUTE_CATEGORY_JAN_4_2012_1150AM)
|
||||
#define BOOST_SPIRIT_X3_ATTRIBUTE_CATEGORY_JAN_4_2012_1150AM
|
||||
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/logical.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/support/category_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_variant.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_range.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/optional_traits.hpp>
|
||||
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/support/category_of.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct unused_type;
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
struct unused_attribute {};
|
||||
struct plain_attribute {};
|
||||
@@ -36,89 +36,60 @@ namespace boost::spirit::x3::traits
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct attribute_category
|
||||
{
|
||||
using type = plain_attribute;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T const> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T&> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T const&> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T&&> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct attribute_category<T const&&> : attribute_category<T> {};
|
||||
|
||||
template <typename T>
|
||||
using attribute_category_t = typename attribute_category<T>::type;
|
||||
: mpl::identity<plain_attribute> {};
|
||||
|
||||
template <>
|
||||
struct attribute_category<unused_type>
|
||||
{
|
||||
using type = unused_attribute;
|
||||
};
|
||||
: mpl::identity<unused_attribute> {};
|
||||
|
||||
template <typename T, typename AttributeCategoryTag>
|
||||
concept CategorizedAttr = std::is_same_v<typename attribute_category<T>::type, AttributeCategoryTag>;
|
||||
template <>
|
||||
struct attribute_category<unused_type const>
|
||||
: mpl::identity<unused_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
concept NonUnusedAttr = !CategorizedAttr<T, unused_attribute>;
|
||||
struct attribute_category< T
|
||||
, typename enable_if<
|
||||
typename mpl::eval_if<
|
||||
fusion::traits::is_sequence<T>
|
||||
, fusion::traits::is_associative<T>
|
||||
, mpl::false_
|
||||
>::type >::type >
|
||||
: mpl::identity<associative_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires
|
||||
fusion::traits::is_sequence<T>::value &&
|
||||
fusion::traits::is_associative<T>::value
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = associative_attribute;
|
||||
};
|
||||
struct attribute_category< T
|
||||
, typename enable_if<
|
||||
mpl::and_<
|
||||
fusion::traits::is_sequence<T>
|
||||
, mpl::not_<fusion::traits::is_associative<T> >
|
||||
> >::type >
|
||||
: mpl::identity<tuple_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires
|
||||
fusion::traits::is_sequence<T>::value &&
|
||||
(!fusion::traits::is_associative<T>::value)
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = tuple_attribute;
|
||||
};
|
||||
struct attribute_category<T,
|
||||
typename enable_if<traits::is_variant<T>>::type>
|
||||
: mpl::identity<variant_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires is_variant_v<T>
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = variant_attribute;
|
||||
};
|
||||
struct attribute_category<T,
|
||||
typename enable_if<traits::is_optional<T>>::type>
|
||||
: mpl::identity<optional_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires is_optional_v<T>
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = optional_attribute;
|
||||
};
|
||||
struct attribute_category<T,
|
||||
typename enable_if<traits::is_range<T>>::type>
|
||||
: mpl::identity<range_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires is_range_v<T>
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = range_attribute;
|
||||
};
|
||||
struct attribute_category< T
|
||||
, typename enable_if<
|
||||
mpl::and_<
|
||||
traits::is_container<T>
|
||||
, mpl::not_<fusion::traits::is_sequence<T> >
|
||||
, mpl::not_<traits::is_range<T> >
|
||||
> >::type >
|
||||
: mpl::identity<container_attribute> {};
|
||||
|
||||
template <typename T>
|
||||
requires
|
||||
(!traits::is_range_v<T>) &&
|
||||
traits::is_container_v<T> &&
|
||||
(!fusion::traits::is_sequence<T>::value)
|
||||
struct attribute_category<T>
|
||||
{
|
||||
using type = container_attribute;
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -9,9 +9,11 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ATTRIBUTE_OF_JAN_7_2012_0914AM)
|
||||
#define BOOST_SPIRIT_X3_ATTRIBUTE_OF_JAN_7_2012_0914AM
|
||||
|
||||
#include <type_traits>
|
||||
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get the attribute type of a component. By default, this gets the
|
||||
@@ -22,37 +24,31 @@ namespace boost::spirit::x3::traits
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct attribute_of;
|
||||
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
using attribute_of_t = typename attribute_of<Component, Context>::type;
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires requires {
|
||||
typename Component::attribute_type;
|
||||
}
|
||||
struct attribute_of<Component, Context>
|
||||
namespace detail
|
||||
{
|
||||
using type = typename Component::attribute_type;
|
||||
};
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct default_attribute_of;
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires requires {
|
||||
typename Component::template attribute<Context>::type;
|
||||
}
|
||||
struct attribute_of<Component, Context>
|
||||
{
|
||||
using type = typename Component::template attribute<Context>::type;
|
||||
};
|
||||
template <typename Component, typename Context>
|
||||
struct default_attribute_of<Component, Context,
|
||||
typename disable_if_substitution_failure<
|
||||
typename Component::attribute_type>::type>
|
||||
: mpl::identity<typename Component::attribute_type> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires Component::is_pass_through_unary
|
||||
struct attribute_of<Component, Context>
|
||||
{
|
||||
static_assert(requires {
|
||||
typename Component::subject_type;
|
||||
});
|
||||
using type = typename attribute_of<typename Component::subject_type, Context>::type;
|
||||
};
|
||||
template <typename Component, typename Context>
|
||||
struct default_attribute_of<Component, Context,
|
||||
typename disable_if_substitution_failure<
|
||||
typename Component::template attribute<Context>::type>::type>
|
||||
: Component::template attribute<Context> {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
template <typename Component, typename Context>
|
||||
struct default_attribute_of<Component, Context,
|
||||
typename enable_if_c<Component::is_pass_through_unary>::type>
|
||||
: attribute_of<typename Component::subject_type, Context>{};
|
||||
}
|
||||
|
||||
template <typename Component, typename Context, typename Enable>
|
||||
struct attribute_of : detail::default_attribute_of<Component, Context> {};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -8,20 +8,19 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ATTRIBUTE_TYPE_JAN_5_2012_0358PM)
|
||||
#define BOOST_SPIRIT_X3_ATTRIBUTE_TYPE_JAN_5_2012_0358PM
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// Retrieve the attribute type to use from the given type.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Retrieve the attribute type to use from the given type
|
||||
//
|
||||
// This is needed to extract the correct attribute type from proxy classes
|
||||
// as utilized in `FUSION_ADAPT_ADT` et. al.
|
||||
// as utilized in FUSION_ADAPT_ADT et. al.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Attribute, typename Enable = void>
|
||||
struct attribute_type
|
||||
{
|
||||
using type = Attribute;
|
||||
};
|
||||
struct attribute_type : mpl::identity<Attribute> {};
|
||||
|
||||
template <typename Attribute>
|
||||
using attribute_type_t = typename attribute_type<Attribute>::type;
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -12,55 +12,49 @@
|
||||
#include <boost/fusion/support/category_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/fusion/include/deque.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/type_traits/make_void.hpp>
|
||||
|
||||
#include <ranges>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename T>
|
||||
struct is_container : std::false_type {};
|
||||
|
||||
// TODO: fully replace this trait using std::ranges
|
||||
template <typename T>
|
||||
requires
|
||||
//std::ranges::range<T> && // TODO: this breaks `fusion::vector<>`; test case in omit.cpp.
|
||||
requires {
|
||||
typename T::value_type;
|
||||
typename T::iterator;
|
||||
typename T::size_type;
|
||||
typename T::reference;
|
||||
}
|
||||
struct is_container<T> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_container_v = is_container<T>::value;
|
||||
|
||||
template <typename T>
|
||||
concept ContainerAttr = is_container_v<std::remove_cvref_t<T>>;
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct is_associative : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
requires requires {
|
||||
typename T::key_type;
|
||||
}
|
||||
struct is_associative<T> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_associative_v = is_associative<T>::value;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This file contains some container utils for stl containers.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, typename Enabler = void>
|
||||
struct is_container_impl : mpl::false_ {};
|
||||
|
||||
template <typename T>
|
||||
struct remove_value_const : std::type_identity<T> {};
|
||||
struct is_container_impl<T, void_t<
|
||||
typename T::value_type, typename T::iterator,
|
||||
typename T::size_type, typename T::reference> > : mpl::true_ {};
|
||||
|
||||
template <typename T, typename Enabler = void>
|
||||
struct is_associative_impl : mpl::false_ {};
|
||||
|
||||
template <typename T>
|
||||
struct is_associative_impl<T, void_t<typename T::key_type>>
|
||||
: mpl::true_ {};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using is_container = typename detail::is_container_impl<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using is_associative = typename detail::is_associative_impl<T>::type;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
struct remove_value_const : mpl::identity<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct remove_value_const<T const> : remove_value_const<T> {};
|
||||
@@ -68,21 +62,18 @@ namespace boost::spirit::x3::traits
|
||||
template <typename F, typename S>
|
||||
struct remove_value_const<std::pair<F, S>>
|
||||
{
|
||||
using first_type = typename remove_value_const<F>::type;
|
||||
using second_type = typename remove_value_const<S>::type;
|
||||
using type = std::pair<first_type, second_type>;
|
||||
typedef typename remove_value_const<F>::type first_type;
|
||||
typedef typename remove_value_const<S>::type second_type;
|
||||
typedef std::pair<first_type, second_type> type;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Container, typename Enable = void>
|
||||
struct container_value
|
||||
: detail::remove_value_const<typename Container::value_type>
|
||||
: detail::remove_value_const<typename Container::value_type>
|
||||
{};
|
||||
|
||||
template <typename Container>
|
||||
using container_value_t = typename container_value<Container>::type;
|
||||
|
||||
template <typename Container>
|
||||
struct container_value<Container const> : container_value<Container> {};
|
||||
|
||||
@@ -91,36 +82,32 @@ namespace boost::spirit::x3::traits
|
||||
// saved to container, we simply return whole fusion::map as is
|
||||
// so that check can be done in traits::is_substitute specialisation
|
||||
template <typename T>
|
||||
struct container_value<
|
||||
T,
|
||||
std::enable_if_t<
|
||||
std::conditional_t<
|
||||
fusion::traits::is_sequence<T>::value,
|
||||
fusion::traits::is_associative<T>,
|
||||
std::false_type
|
||||
>::type::value
|
||||
>
|
||||
> : std::type_identity<T> {};
|
||||
struct container_value<T
|
||||
, typename enable_if<typename mpl::eval_if <
|
||||
fusion::traits::is_sequence<T>
|
||||
, fusion::traits::is_associative<T>
|
||||
, mpl::false_ >::type >::type>
|
||||
: mpl::identity<T> {};
|
||||
|
||||
template <>
|
||||
struct container_value<unused_type> : std::type_identity<unused_type> {};
|
||||
struct container_value<unused_type> : mpl::identity<unused_type> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Container, typename Enable = void>
|
||||
struct container_iterator
|
||||
: std::type_identity<typename Container::iterator> {};
|
||||
: mpl::identity<typename Container::iterator> {};
|
||||
|
||||
template <typename Container>
|
||||
struct container_iterator<Container const>
|
||||
: std::type_identity<typename Container::const_iterator> {};
|
||||
: mpl::identity<typename Container::const_iterator> {};
|
||||
|
||||
template <>
|
||||
struct container_iterator<unused_type>
|
||||
: std::type_identity<unused_type const*> {};
|
||||
: mpl::identity<unused_type const*> {};
|
||||
|
||||
template <>
|
||||
struct container_iterator<unused_type const>
|
||||
: std::type_identity<unused_type const*> {};
|
||||
: mpl::identity<unused_type const*> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Container, typename T>
|
||||
@@ -169,13 +156,13 @@ namespace boost::spirit::x3::traits
|
||||
{
|
||||
private:
|
||||
template <typename Iterator>
|
||||
static void insert(Container& c, Iterator first, Iterator last, std::false_type)
|
||||
static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
|
||||
{
|
||||
c.insert(c.end(), first, last);
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static void insert(Container& c, Iterator first, Iterator last, std::true_type)
|
||||
static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
|
||||
{
|
||||
c.insert(first, last);
|
||||
}
|
||||
@@ -203,26 +190,23 @@ namespace boost::spirit::x3::traits
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Container, typename Enable = void>
|
||||
struct is_empty_container;
|
||||
|
||||
[[nodiscard]] constexpr bool is_empty(unused_type) noexcept
|
||||
struct is_empty_container
|
||||
{
|
||||
return true;
|
||||
}
|
||||
static bool call(Container const& c)
|
||||
{
|
||||
return c.empty();
|
||||
}
|
||||
};
|
||||
|
||||
template <ContainerAttr Container>
|
||||
[[nodiscard]] constexpr bool is_empty(Container const& c) noexcept
|
||||
template <typename Container>
|
||||
inline bool is_empty(Container const& c)
|
||||
{
|
||||
return is_empty_container<Container>::call(c);
|
||||
}
|
||||
|
||||
template <ContainerAttr Container>
|
||||
requires requires {
|
||||
std::ranges::empty(std::declval<Container const&>());
|
||||
}
|
||||
[[nodiscard]] constexpr bool is_empty(Container const& c) noexcept
|
||||
inline bool is_empty(unused_type)
|
||||
{
|
||||
return std::ranges::empty(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -340,17 +324,17 @@ namespace boost::spirit::x3::traits
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct build_container : std::type_identity<std::vector<T>> {};
|
||||
struct build_container : mpl::identity<std::vector<T>> {};
|
||||
|
||||
template <typename T>
|
||||
struct build_container<boost::fusion::deque<T> > : build_container<T> {};
|
||||
|
||||
template <>
|
||||
struct build_container<unused_type> : std::type_identity<unused_type> {};
|
||||
struct build_container<unused_type> : mpl::identity<unused_type> {};
|
||||
|
||||
template <>
|
||||
struct build_container<char> : std::type_identity<std::string> {};
|
||||
struct build_container<char> : mpl::identity<std::string> {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
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,21 +8,20 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_HANDLES_CONTAINER_DEC_18_2010_0920AM)
|
||||
#define BOOST_SPIRIT_X3_HANDLES_CONTAINER_DEC_18_2010_0920AM
|
||||
|
||||
#include <type_traits>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Whether a component handles container attributes intrinsically
|
||||
// (or whether container attributes need to be split up separately).
|
||||
// By default, this gets the Component's handles_container nested value.
|
||||
// Components may specialize this if such a handles_container is not
|
||||
// Components may specialize this if such a handles_container is not
|
||||
// readily available (e.g. expensive to compute at compile time).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct handles_container : std::bool_constant<Component::handles_container> {};
|
||||
struct handles_container : mpl::bool_<Component::handles_container> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
constexpr bool handles_container_v = handles_container<Component, Context>::value;
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -10,54 +10,50 @@
|
||||
#define BOOST_SPIRIT_X3_HAS_ATTRIBUTE_JUN_6_2012_1714PM
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct unused_type;
|
||||
} // boost::spirit::x3
|
||||
}}}
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// TODO: make these 'Component' depend on the concept.
|
||||
// It is currently hard to implement due to circular dependency.
|
||||
|
||||
// Whether a component has an attribute. By default, this compares the
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Whether a component has an attribute. By default, this compares the
|
||||
// component attribute against unused_type. If the component provides a
|
||||
// nested constant expression has_attribute as a hint, that value is used
|
||||
// instead. Components may specialize this.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct has_attribute
|
||||
struct has_attribute;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static_assert(requires {
|
||||
typename attribute_of<Component, Context>::type;
|
||||
});
|
||||
static constexpr bool value = !std::is_same_v<attribute_of_t<Component, Context>, unused_type>;
|
||||
};
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct default_has_attribute
|
||||
: mpl::not_<is_same<unused_type,
|
||||
typename attribute_of<Component, Context>::type>> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
constexpr bool has_attribute_v = has_attribute<Component, Context>::value;
|
||||
template <typename Component, typename Context>
|
||||
struct default_has_attribute<Component, Context,
|
||||
typename disable_if_substitution_failure<
|
||||
mpl::bool_<Component::has_attribute>>::type>
|
||||
: mpl::bool_<Component::has_attribute> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
struct default_has_attribute<Component, Context,
|
||||
typename enable_if_c<Component::is_pass_through_unary>::type>
|
||||
: has_attribute<typename Component::subject_type, Context> {};
|
||||
}
|
||||
|
||||
template <typename Component, typename Context, typename Enable>
|
||||
struct has_attribute : detail::default_has_attribute<Component, Context> {};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires requires {
|
||||
{ Component::has_attribute } -> std::same_as<bool>;
|
||||
}
|
||||
struct has_attribute<Component, Context>
|
||||
: std::bool_constant<Component::has_attribute>
|
||||
{};
|
||||
|
||||
template <typename Component, typename Context>
|
||||
requires Component::is_pass_through_unary
|
||||
struct has_attribute<Component, Context>
|
||||
{
|
||||
static_assert(requires {
|
||||
typename Component::subject_type;
|
||||
});
|
||||
static constexpr bool value = has_attribute_v<typename Component::subject_type, Context>;
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2014 Agustin Berge
|
||||
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,19 +8,26 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_IS_PARSER_MAY_20_2013_0235PM)
|
||||
#define BOOST_SPIRIT_X3_IS_PARSER_MAY_20_2013_0235PM
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/spirit/home/x3/core/parser.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// is_parser<T>: metafunction that evaluates to `std::true_type` if `T`
|
||||
// models `X3Subject`, `std::false_type` otherwise
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// is_parser<T>: metafunction that evaluates to mpl::true_ if a type T
|
||||
// can be used as a parser, mpl::false_ otherwise
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Enable = void>
|
||||
struct [[deprecated("Use the concept `x3::X3Subject`")]]
|
||||
is_parser : std::bool_constant<X3Subject<T>>
|
||||
struct is_parser
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
template <typename T>
|
||||
struct is_parser<T, typename disable_if_substitution_failure<
|
||||
typename extension::as_parser<T>::type>::type>
|
||||
: mpl::true_
|
||||
{};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -9,8 +9,6 @@
|
||||
#define BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/tuple_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/optional_traits.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/map.hpp>
|
||||
#include <boost/fusion/include/value_at_key.hpp>
|
||||
@@ -22,148 +20,140 @@
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/mpl/logical.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/count_if.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Find out if T can be a (strong) substitute for Attribute
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Attribute, typename Enable = void>
|
||||
struct is_substitute;
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
constexpr bool is_substitute_v = is_substitute<T, Attribute>::value;
|
||||
|
||||
template <typename Variant, typename Attribute>
|
||||
struct variant_has_substitute;
|
||||
|
||||
// TODO: reduce MPL usage
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, typename Attribute>
|
||||
struct value_type_is_substitute
|
||||
: is_substitute<container_value_t<T>, container_value_t<Attribute>>
|
||||
: is_substitute<
|
||||
typename container_value<T>::type
|
||||
, typename container_value<Attribute>::type>
|
||||
{};
|
||||
|
||||
template <typename T, typename Attribute, typename Enable = void>
|
||||
struct is_substitute_impl : std::false_type {};
|
||||
struct is_substitute_impl : mpl::false_ {};
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
requires std::conjunction_v<
|
||||
fusion::traits::is_sequence<T>,
|
||||
fusion::traits::is_sequence<Attribute>
|
||||
>
|
||||
struct is_substitute_impl<T, Attribute>
|
||||
: mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>>
|
||||
{};
|
||||
struct is_substitute_impl<T, Attribute,
|
||||
typename enable_if<
|
||||
mpl::and_<
|
||||
fusion::traits::is_sequence<T>,
|
||||
fusion::traits::is_sequence<Attribute>,
|
||||
mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>>
|
||||
>
|
||||
>::type>
|
||||
: mpl::true_ {};
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
requires
|
||||
is_container_v<T> &&
|
||||
is_container_v<Attribute>
|
||||
struct is_substitute_impl<T, Attribute>
|
||||
: value_type_is_substitute<T, Attribute>
|
||||
{};
|
||||
struct is_substitute_impl<T, Attribute,
|
||||
typename enable_if<
|
||||
mpl::and_<
|
||||
is_container<T>,
|
||||
is_container<Attribute>,
|
||||
value_type_is_substitute<T, Attribute>
|
||||
>
|
||||
>::type>
|
||||
: mpl::true_ {};
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
requires is_variant_v<Attribute>
|
||||
struct is_substitute_impl<T, Attribute>
|
||||
: variant_has_substitute<Attribute, T>
|
||||
struct is_substitute_impl<T, Attribute,
|
||||
typename enable_if<
|
||||
is_variant<Attribute>
|
||||
>::type>
|
||||
: variant_has_substitute<Attribute, T>
|
||||
{};
|
||||
}
|
||||
|
||||
template <typename T, typename Attribute, typename Enable>
|
||||
template <typename T, typename Attribute, typename Enable /*= void*/>
|
||||
struct is_substitute
|
||||
: std::disjunction<
|
||||
std::is_same<T, Attribute>,
|
||||
detail::is_substitute_impl<T, Attribute>
|
||||
>
|
||||
{};
|
||||
: mpl::or_<
|
||||
is_same<T, Attribute>,
|
||||
detail::is_substitute_impl<T, Attribute>> {};
|
||||
|
||||
// for reference T
|
||||
template <typename T, typename Attribute>
|
||||
struct is_substitute<T&, Attribute>
|
||||
: is_substitute<T, Attribute>
|
||||
{};
|
||||
template <typename T, typename Attribute, typename Enable>
|
||||
struct is_substitute<T&, Attribute, Enable>
|
||||
: is_substitute<T, Attribute, Enable> {};
|
||||
|
||||
// for reference Attribute
|
||||
template <typename T, typename Attribute>
|
||||
struct is_substitute<T, Attribute&>
|
||||
: is_substitute<T, Attribute>
|
||||
{};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename Key, typename Value, typename Map>
|
||||
struct has_fusion_kv_in_map : std::false_type {};
|
||||
|
||||
template <typename Key, typename Value, typename Map>
|
||||
requires fusion::result_of::has_key<Map, Key>::value
|
||||
struct has_fusion_kv_in_map<Key, Value, Map> : is_substitute<
|
||||
typename fusion::result_of::value_at_key<Map, Key>::type,
|
||||
Value
|
||||
> {};
|
||||
} // detail
|
||||
template <typename T, typename Attribute, typename Enable>
|
||||
struct is_substitute<T, Attribute&, Enable>
|
||||
: is_substitute<T, Attribute, Enable> {};
|
||||
|
||||
// 2 element mpl tuple is compatible with fusion::map if:
|
||||
// - it's first element type is existing key in map
|
||||
// - it second element type is compatible to type stored at the key in map
|
||||
template <typename T, typename Attribute>
|
||||
requires std::conjunction_v<
|
||||
fusion::traits::is_sequence<T>,
|
||||
fusion::traits::is_sequence<Attribute>,
|
||||
traits::has_size<T, 2>,
|
||||
fusion::traits::is_associative<Attribute>
|
||||
>
|
||||
struct is_substitute<T, Attribute>
|
||||
struct is_substitute<T, Attribute
|
||||
, typename enable_if<
|
||||
typename mpl::eval_if<
|
||||
mpl::and_<fusion::traits::is_sequence<T>
|
||||
, fusion::traits::is_sequence<Attribute>>
|
||||
, mpl::and_<traits::has_size<T, 2>
|
||||
, fusion::traits::is_associative<Attribute>>
|
||||
, mpl::false_>::type>::type>
|
||||
|
||||
{
|
||||
// Checking that "p_key >> p_value" parser can
|
||||
// checking that "p_key >> p_value" parser can
|
||||
// store it's result in fusion::map attribute
|
||||
using p_key = typename mpl::at_c<T, 0>::type;
|
||||
using p_value = typename mpl::at_c<T, 1>::type;
|
||||
typedef typename mpl::at_c<T, 0>::type p_key;
|
||||
typedef typename mpl::at_c<T, 1>::type p_value;
|
||||
|
||||
// For simple `p_key` type we just check that
|
||||
// for simple p_key type we just check that
|
||||
// such key can be found in attr and that value under that key
|
||||
// matches `p_value`.
|
||||
// matches p_value
|
||||
template <typename Key, typename Value, typename Map>
|
||||
struct has_kv_in_map
|
||||
: mpl::eval_if<
|
||||
fusion::result_of::has_key<Map, Key>
|
||||
, mpl::apply<
|
||||
is_substitute<
|
||||
fusion::result_of::value_at_key<mpl::_1, Key>
|
||||
, Value>
|
||||
, Map>
|
||||
, mpl::false_>
|
||||
{};
|
||||
|
||||
// Otherwise, if p_key is variant over multiple types (as a result of
|
||||
// "(key1|key2|key3) >> p_value" parser), check that all
|
||||
// keys are found in `fusion::map` attribute and that values
|
||||
// under these keys match `p_value`.
|
||||
// if p_key is variant over multiple types (as a result of
|
||||
// "(key1|key2|key3) >> p_value" parser) check that all
|
||||
// keys are found in fusion::map attribute and that values
|
||||
// under these keys match p_value
|
||||
template <typename Variant>
|
||||
struct variant_kv
|
||||
: mpl::equal_to<
|
||||
mpl::size<typename Variant::types>,
|
||||
mpl::size<
|
||||
mpl::filter_view<
|
||||
typename Variant::types,
|
||||
detail::has_fusion_kv_in_map<mpl::_1, p_value, Attribute>
|
||||
>
|
||||
>
|
||||
mpl::size< typename Variant::types>
|
||||
, mpl::size< mpl::filter_view<typename Variant::types
|
||||
, has_kv_in_map<mpl::_1, p_value, Attribute>>>
|
||||
>
|
||||
{};
|
||||
|
||||
static constexpr bool value = std::conditional_t<
|
||||
is_variant_v<p_key>,
|
||||
variant_kv<p_key>,
|
||||
detail::has_fusion_kv_in_map<p_key, p_value, Attribute>
|
||||
>::value;
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_variant<p_key>
|
||||
, variant_kv<p_key>
|
||||
, has_kv_in_map<p_key, p_value, Attribute>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
template <typename T, typename Attribute>
|
||||
struct [[deprecated("Use std::optional")]] is_substitute<boost::optional<T>, boost::optional<Attribute>>
|
||||
: is_substitute<T, Attribute>
|
||||
{};
|
||||
#endif
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
struct is_substitute<std::optional<T>, std::optional<Attribute>>
|
||||
: is_substitute<T, Attribute>
|
||||
{};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
struct is_substitute<optional<T>, optional<Attribute>>
|
||||
: is_substitute<T, Attribute> {};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -8,40 +8,34 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_IS_VARIANT_JAN_10_2012_0823AM)
|
||||
#define BOOST_SPIRIT_X3_IS_VARIANT_JAN_10_2012_0823AM
|
||||
|
||||
#include <boost/variant/variant_fwd.hpp> // TODO: remove this
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// TODO: define a legit concept for determining variant-like types
|
||||
namespace detail
|
||||
{
|
||||
// By declaring a nested struct in your class/struct, you tell
|
||||
// spirit that it is regarded as a variant type. The minimum
|
||||
// required interface for such a variant is that it has constructors
|
||||
// for various types supported by your variant and a typedef 'types'
|
||||
// which is an mpl sequence of the contained types.
|
||||
//
|
||||
// This is an intrusive interface. For a non-intrusive interface,
|
||||
// use the is_variant trait.
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(adapted_variant_tag)
|
||||
}
|
||||
|
||||
template <typename T, typename Enabled = void>
|
||||
struct is_variant : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_variant_v = is_variant<T>::value;
|
||||
|
||||
// By declaring a nested struct named `adapted_variant_tag` in
|
||||
// your class, you tell spirit that it is regarded as a variant type.
|
||||
// The minimum required interface for such a variant is that it has
|
||||
// constructors for various types supported by your variant and a
|
||||
// typedef 'types' which is an mpl sequence of the contained types.
|
||||
// Note (2025): The above spec is obsolete and will change in the near future.
|
||||
//
|
||||
// This is an intrusive interface. For a non-intrusive interface,
|
||||
// specialize the is_variant trait.
|
||||
template <typename T>
|
||||
requires requires {
|
||||
typename T::adapted_variant_tag;
|
||||
}
|
||||
struct is_variant<T> : std::true_type
|
||||
template <typename T, typename Enable = void>
|
||||
struct is_variant
|
||||
: detail::has_adapted_variant_tag<T>
|
||||
{};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
|
||||
: std::true_type
|
||||
: mpl::true_
|
||||
{};
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -17,259 +17,212 @@
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/front.hpp>
|
||||
#include <boost/fusion/include/move.hpp>
|
||||
#include <boost/fusion/include/copy.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
# include <boost/range/iterator_range_core.hpp> // deprecated
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <iterator>
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// Identical types ---------------------------------------
|
||||
//
|
||||
// Note that these overloads must be strictly "more constrained"
|
||||
// than any of the other overloads.
|
||||
//
|
||||
// Such resolution should be possible even without an extra
|
||||
// constraint that checks `std::is_same_v<Source, Dest>`, thanks to
|
||||
// the ordinary overload resolution rules of C++.
|
||||
template <typename Source, typename Dest>
|
||||
inline void move_to(Source&& src, Dest& dest);
|
||||
|
||||
template <typename T>
|
||||
requires (!CategorizedAttr<T, unused_attribute>)
|
||||
constexpr void move_to(T const&& src, T& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<T&, T const&&>)
|
||||
inline void move_to(T& src, T& dest);
|
||||
|
||||
template <typename T>
|
||||
inline void move_to(T const& src, T& dest);
|
||||
|
||||
template <typename T>
|
||||
inline void move_to(T&& src, T& dest);
|
||||
|
||||
template <typename Iterator, typename Dest>
|
||||
inline void move_to(Iterator first, Iterator last, Dest& dest);
|
||||
|
||||
template <typename Dest>
|
||||
inline void move_to(unused_type, Dest&) {}
|
||||
|
||||
template <typename Source>
|
||||
inline void move_to(Source&, unused_type) {}
|
||||
|
||||
inline void move_to(unused_type, unused_type) {}
|
||||
|
||||
template <typename Iterator>
|
||||
inline void
|
||||
move_to(Iterator, Iterator, unused_type) {}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source&, Dest&, unused_attribute) {}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_plain(Source& src, Dest& dest, mpl::false_) // src is not a single-element tuple
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_plain(Source& src, Dest& dest, mpl::true_) // src is a single-element tuple
|
||||
{
|
||||
dest = std::move(fusion::front(src));
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, plain_attribute)
|
||||
{
|
||||
typename mpl::and_<
|
||||
fusion::traits::is_sequence<Source>,
|
||||
is_size_one_sequence<Source> >
|
||||
is_single_element_sequence;
|
||||
|
||||
move_to_plain(src, dest, is_single_element_sequence);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline typename enable_if<is_container<Source>>::type
|
||||
move_to(Source& src, Dest& dest, container_attribute)
|
||||
{
|
||||
traits::move_to(src.begin(), src.end(), dest);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline typename enable_if<
|
||||
mpl::and_<
|
||||
is_same_size_sequence<Dest, Source>,
|
||||
mpl::not_<is_size_one_sequence<Dest> > >
|
||||
>::type
|
||||
move_to(Source& src, Dest& dest, tuple_attribute)
|
||||
{
|
||||
fusion::move(std::move(src), dest);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline typename enable_if<
|
||||
is_size_one_sequence<Dest>
|
||||
>::type
|
||||
move_to(Source& src, Dest& dest, tuple_attribute)
|
||||
{
|
||||
traits::move_to(src, fusion::front(dest));
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, variant_attribute, mpl::false_)
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_variant_from_single_element_sequence(Source& src, Dest& dest, mpl::false_)
|
||||
{
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// cannot directly hold. We'll try to unwrap the single element fusion sequence.
|
||||
|
||||
// Make sure that the Dest variant can really hold Source
|
||||
static_assert(variant_has_substitute<Dest, typename fusion::result_of::front<Source>::type>::value,
|
||||
"Error! The destination variant (Dest) cannot hold the source type (Source)");
|
||||
|
||||
dest = std::move(fusion::front(src));
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_variant_from_single_element_sequence(Source& src, Dest& dest, mpl::true_)
|
||||
{
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// *can* directly hold.
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, variant_attribute, mpl::true_)
|
||||
{
|
||||
move_to_variant_from_single_element_sequence(src, dest, variant_has_substitute<Dest, Source>());
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, variant_attribute tag)
|
||||
{
|
||||
move_to(src, dest, tag, is_size_one_sequence<Source>());
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source& src, Dest& dest, optional_attribute)
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
inline void
|
||||
move_to(Iterator, Iterator, unused_type, unused_attribute) {}
|
||||
|
||||
template <typename Iterator, typename Dest>
|
||||
inline void
|
||||
move_to(Iterator first, Iterator last, Dest& dest, container_attribute)
|
||||
{
|
||||
if (is_empty(dest))
|
||||
dest = Dest(first, last);
|
||||
else
|
||||
append(dest, first, last);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Dest>
|
||||
inline typename enable_if<
|
||||
is_size_one_sequence<Dest>
|
||||
>::type
|
||||
move_to(Iterator first, Iterator last, Dest& dest, tuple_attribute)
|
||||
{
|
||||
traits::move_to(first, last, fusion::front(dest));
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
inline void
|
||||
move_to(Iterator first, Iterator last, boost::iterator_range<Iterator>& rng, range_attribute)
|
||||
{
|
||||
rng = {first, last};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void move_to(Source&& src, Dest& dest)
|
||||
{
|
||||
detail::move_to(src, dest, typename attribute_category<Dest>::type());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void move_to(T& src, T& dest)
|
||||
{
|
||||
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires (!CategorizedAttr<T, unused_attribute>)
|
||||
constexpr void move_to(T&& src, T& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<T&, T&&>)
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires (!CategorizedAttr<T, unused_attribute>)
|
||||
constexpr void move_to(T const& src, T& dest)
|
||||
noexcept(std::is_nothrow_copy_assignable_v<T>)
|
||||
inline void move_to(T const& src, T& dest)
|
||||
{
|
||||
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
||||
dest = src;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires (!CategorizedAttr<T, unused_attribute>)
|
||||
constexpr void move_to(T&, T&) noexcept
|
||||
inline void move_to(T&& src, T& dest)
|
||||
{
|
||||
static_assert(
|
||||
!std::is_const_v<T>,
|
||||
"`x3::move_to(T const&, T const&)` is not allowed"
|
||||
);
|
||||
|
||||
static_assert(
|
||||
false,
|
||||
"lvalue reference detected on the `src` argument of `x3::move_to`. "
|
||||
"The caller is definitely lacking `std::move` or `std::forward`. If you "
|
||||
"intend to *copy* the mutable value, apply `x3::move_to(std::as_const(attr_), attr)`."
|
||||
);
|
||||
// Banned: possible, but bug-prone.
|
||||
// dest = std::move(src);
|
||||
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
// unused_type -------------------------------------------
|
||||
template <typename Source, typename Dest>
|
||||
requires
|
||||
CategorizedAttr<Source, unused_attribute> ||
|
||||
CategorizedAttr<Dest, unused_attribute>
|
||||
constexpr void move_to(Source&&, Dest&) noexcept
|
||||
template <typename Iterator, typename Dest>
|
||||
inline void move_to(Iterator first, Iterator last, Dest& dest)
|
||||
{
|
||||
// $$$ Use std::move_iterator when iterator is not a const-iterator $$$
|
||||
detail::move_to(first, last, dest, typename attribute_category<Dest>::type());
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Dest>
|
||||
requires
|
||||
std::is_same_v<std::remove_const_t<Dest>, unused_type>
|
||||
constexpr void
|
||||
move_to(It, Se, Dest&) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
// Category specific --------------------------------------
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<plain_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Source>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(noexcept(dest = std::forward_like<Source>(fusion::front(std::forward<Source>(src)))))
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
dest = std::forward_like<Source>(fusion::front(std::forward<Source>(src)));
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<plain_attribute> Dest>
|
||||
requires (!is_size_one_sequence_v<Source>)
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
static_assert(std::is_assignable_v<Dest&, Source&&>);
|
||||
dest = std::forward<Source>(src);
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<tuple_attribute> Dest>
|
||||
requires
|
||||
is_same_size_sequence_v<Dest, Source> &&
|
||||
(!is_size_one_sequence_v<Dest>)
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(
|
||||
std::is_rvalue_reference_v<Source&&> ?
|
||||
noexcept(fusion::move(std::move(src), dest)) :
|
||||
noexcept(fusion::copy(src, dest))
|
||||
)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
if constexpr (std::is_rvalue_reference_v<Source&&>)
|
||||
{
|
||||
fusion::move(std::move(src), dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
fusion::copy(src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<variant_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Source> && variant_has_substitute_v<Dest, Source>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// *can* directly hold.
|
||||
dest = std::forward<Source>(src);
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<variant_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Source> && (!variant_has_substitute_v<Dest, Source>)
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(noexcept(dest = std::forward_like<Source>(fusion::front(std::forward<Source>(src)))))
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// cannot directly hold. We'll try to unwrap the single element fusion sequence.
|
||||
|
||||
// Make sure that the Dest variant can really hold Source
|
||||
static_assert(
|
||||
variant_has_substitute_v<Dest, typename fusion::result_of::front<Source>::type>,
|
||||
"Error! The destination variant (Dest) cannot hold the source type (Source)"
|
||||
);
|
||||
|
||||
dest = std::forward_like<Source>(fusion::front(std::forward<Source>(src)));
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<variant_attribute> Dest>
|
||||
requires (!is_size_one_sequence_v<Source>)
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
dest = std::forward<Source>(src);
|
||||
}
|
||||
|
||||
template <NonUnusedAttr Source, CategorizedAttr<optional_attribute> Dest>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
dest = std::forward<Source>(src);
|
||||
}
|
||||
|
||||
// Containers -------------------------------------------------
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, CategorizedAttr<container_attribute> Dest>
|
||||
constexpr void
|
||||
move_to(It first, Se last, Dest& dest)
|
||||
// never noexcept, requires container insertion
|
||||
{
|
||||
if (traits::is_empty(dest))
|
||||
{
|
||||
dest = Dest(first, last);
|
||||
}
|
||||
else
|
||||
{
|
||||
traits::append(dest, first, last);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
|
||||
template <std::forward_iterator It>
|
||||
constexpr void
|
||||
move_to(It first, It last, boost::iterator_range<It>& rng)
|
||||
{
|
||||
rng = {first, last};
|
||||
}
|
||||
#endif
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, std::ranges::subrange_kind Kind>
|
||||
constexpr void
|
||||
move_to(It first, Se last, std::ranges::subrange<It, Se, Kind>& rng)
|
||||
{
|
||||
rng = std::ranges::subrange<It, Se, Kind>(std::move(first), std::move(last));
|
||||
}
|
||||
|
||||
template <std::forward_iterator It, std::sentinel_for<It> Se, CategorizedAttr<tuple_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Dest>
|
||||
constexpr void
|
||||
move_to(It first, Se last, Dest& dest)
|
||||
noexcept(noexcept(traits::move_to(first, last, fusion::front(dest))))
|
||||
{
|
||||
traits::move_to(first, last, fusion::front(dest));
|
||||
}
|
||||
|
||||
template <ContainerAttr Source, CategorizedAttr<container_attribute> Dest>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
// TODO: noexcept
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
if constexpr (std::is_rvalue_reference_v<Source&&>)
|
||||
{
|
||||
traits::move_to(std::make_move_iterator(std::ranges::begin(src)), std::make_move_iterator(std::ranges::end(src)), dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
traits::move_to(std::ranges::begin(src), std::ranges::end(src), dest);
|
||||
}
|
||||
}
|
||||
|
||||
// Size-one fusion tuple forwarding
|
||||
template <NonUnusedAttr Source, CategorizedAttr<tuple_attribute> Dest>
|
||||
requires is_size_one_sequence_v<Dest>
|
||||
constexpr void
|
||||
move_to(Source&& src, Dest& dest)
|
||||
noexcept(noexcept(traits::move_to(std::forward<Source>(src), fusion::front(dest))))
|
||||
{
|
||||
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
|
||||
|
||||
traits::move_to(std::forward<Source>(src), fusion::front(dest));
|
||||
}
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -10,87 +10,65 @@
|
||||
#define BOOST_SPIRIT_X3_OPTIONAL_TRAITS_FEBRUARY_06_2007_1001AM
|
||||
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
# define BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL 1
|
||||
#endif
|
||||
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
# include <boost/optional/optional.hpp>
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename Enable = void>
|
||||
struct is_optional : std::false_type {};
|
||||
struct is_optional
|
||||
: mpl::false_
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_optional_v = is_optional<T>::value;
|
||||
struct is_optional<boost::optional<T>>
|
||||
: mpl::true_
|
||||
{};
|
||||
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
template <typename T>
|
||||
struct [[deprecated("Use std::optional")]] is_optional<boost::optional<T>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct is_optional<std::optional<T>> : std::true_type {};
|
||||
|
||||
// Build a optional type from T. Return unused_type if T is unused_type.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// build_optional
|
||||
//
|
||||
// Build a boost::optional from T. Return unused_type if T is unused_type.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct build_optional
|
||||
{
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
using type [[deprecated("Use std::optional")]] = boost::optional<T>;
|
||||
#else
|
||||
using type = std::optional<T>;
|
||||
#endif
|
||||
typedef boost::optional<T> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using build_optional_t = typename build_optional<T>::type;
|
||||
|
||||
#if BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL
|
||||
template <typename T>
|
||||
struct [[deprecated("Use std::optional")]] build_optional<boost::optional<T>>
|
||||
struct build_optional<boost::optional<T> >
|
||||
{
|
||||
using type = boost::optional<T>;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct build_optional<std::optional<T>>
|
||||
{
|
||||
using type = std::optional<T>;
|
||||
typedef boost::optional<T> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct build_optional<unused_type>
|
||||
{
|
||||
using type = unused_type;
|
||||
typedef unused_type type;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// optional_value
|
||||
//
|
||||
// Get the optional's value_type. Handles unused_type as well.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct optional_value { using type = typename T::value_type; };
|
||||
struct optional_value : mpl::identity<T> {};
|
||||
|
||||
template <typename T>
|
||||
using optional_value_t = typename optional_value<T>::type;
|
||||
struct optional_value<boost::optional<T> >
|
||||
: mpl::identity<T> {};
|
||||
|
||||
template <>
|
||||
struct optional_value<unused_type>
|
||||
{
|
||||
using type = unused_type;
|
||||
};
|
||||
: mpl::identity<unused_type> {};
|
||||
|
||||
template <>
|
||||
struct optional_value<unused_type const>
|
||||
{
|
||||
using type = unused_type;
|
||||
};
|
||||
: mpl::identity<unused_type> {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2019 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,29 +7,28 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_PSEUDO_ATTRIBUTE_OF_MAY_15_2019_1012PM)
|
||||
#define BOOST_SPIRIT_X3_PSEUDO_ATTRIBUTE_OF_MAY_15_2019_1012PM
|
||||
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Pseudo attributes are placeholders for parsers that can only know
|
||||
// its actual attribute at parse time. This trait customization point
|
||||
// provides a mechanism to convert the trait to the actual trait at
|
||||
// parse time.
|
||||
template <typename Context, typename Attribute, std::forward_iterator It, std::sentinel_for<It> Se = It, typename Enable = void>
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Context, typename Attribute, typename Iterator
|
||||
, typename Enable = void>
|
||||
struct pseudo_attribute
|
||||
{
|
||||
using attribute_type = Attribute;
|
||||
using type = Attribute;
|
||||
|
||||
[[nodiscard]] static constexpr type&& call(It&, Se const&, Attribute&& attribute) noexcept
|
||||
static type&& call(Iterator&, Iterator const&, attribute_type&& attribute)
|
||||
{
|
||||
return static_cast<type&&>(attribute);
|
||||
return std::forward<type>(attribute);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Context, typename Attribute, std::forward_iterator It, std::sentinel_for<It> Se>
|
||||
using pseudo_attribute_t = typename pseudo_attribute<Context, Attribute, It, Se>::type;
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2012 Hartmut Kaiser
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -9,7 +9,9 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ATTRIBUTE_TRANSFORM_JAN_8_2012_0721PM)
|
||||
#define BOOST_SPIRIT_X3_ATTRIBUTE_TRANSFORM_JAN_8_2012_0721PM
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// transform_attribute
|
||||
@@ -22,12 +24,6 @@ namespace boost::spirit::x3::traits
|
||||
template <typename Exposed, typename Transformed, typename Tag
|
||||
, typename Enable = void>
|
||||
struct transform_attribute;
|
||||
|
||||
template <typename Exposed, typename Transformed, typename Tag>
|
||||
concept Transformable = requires {
|
||||
typename transform_attribute<Exposed, Transformed, Tag>::type;
|
||||
};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*=============================================================================
|
||||
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,69 +10,48 @@
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/is_view.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
// Note that these metafunctions MUST be explicitly derived from `std::bool_constant`,
|
||||
// because they are used for tag dispatch in some locations.
|
||||
// Beware that `std::conjunction` / `std::disjunction` is not guaranteed to derive
|
||||
// from `std::bool_constant`.
|
||||
|
||||
template <typename A, typename B>
|
||||
struct has_same_size
|
||||
: std::bool_constant<
|
||||
fusion::result_of::size<std::remove_cvref_t<A>>::value ==
|
||||
fusion::result_of::size<std::remove_cvref_t<B>>::value
|
||||
>
|
||||
: mpl::bool_<(
|
||||
fusion::result_of::size<A>::value ==
|
||||
fusion::result_of::size<B>::value
|
||||
)>
|
||||
{};
|
||||
|
||||
template <typename A, typename B>
|
||||
constexpr bool has_same_size_v = has_same_size<A, B>::value;
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct has_size
|
||||
: std::bool_constant<fusion::result_of::size<std::remove_cvref_t<T>>::value == N>
|
||||
: mpl::bool_<(fusion::result_of::size<T>::value == N)>
|
||||
{};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
constexpr bool has_size_v = has_size<T, N>::value;
|
||||
|
||||
template <typename A, typename B>
|
||||
struct is_same_size_sequence
|
||||
: std::bool_constant<std::conjunction_v<
|
||||
fusion::traits::is_sequence<std::remove_cvref_t<A>>,
|
||||
fusion::traits::is_sequence<std::remove_cvref_t<B>>,
|
||||
has_same_size<A, B>
|
||||
>>
|
||||
: mpl::and_<
|
||||
fusion::traits::is_sequence<A>
|
||||
, fusion::traits::is_sequence<B>
|
||||
, has_same_size<A, B>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename A, typename B>
|
||||
constexpr bool is_same_size_sequence_v = is_same_size_sequence<A, B>::value;
|
||||
|
||||
template <typename Seq>
|
||||
struct is_size_one_sequence
|
||||
: std::bool_constant<std::conjunction_v<
|
||||
fusion::traits::is_sequence<std::remove_cvref_t<Seq>>,
|
||||
has_size<Seq, 1>
|
||||
>>
|
||||
: mpl::and_<
|
||||
fusion::traits::is_sequence<Seq>
|
||||
, has_size<Seq, 1>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Seq>
|
||||
constexpr bool is_size_one_sequence_v = is_size_one_sequence<Seq>::value;
|
||||
|
||||
template <typename View>
|
||||
struct is_size_one_view
|
||||
: std::bool_constant<std::conjunction_v<
|
||||
fusion::traits::is_view<std::remove_cvref_t<View>>,
|
||||
has_size<View, 1>
|
||||
>>
|
||||
: mpl::and_<
|
||||
fusion::traits::is_view<View>
|
||||
, has_size<View, 1>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename View>
|
||||
constexpr bool is_size_one_view_v = is_size_one_view<View>::value;
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -9,9 +9,9 @@
|
||||
#define BOOST_SPIRIT_X3_VARIANT_FIND_SUBSTITUTE_APR_18_2014_930AM
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
|
||||
#include <boost/mpl/find.hpp> // TODO: remove this
|
||||
#include <boost/mpl/find.hpp>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Variant, typename T>
|
||||
struct variant_find_substitute
|
||||
@@ -19,34 +19,33 @@ namespace boost::spirit::x3::traits
|
||||
// Get the type from the Variant that can be a substitute for T.
|
||||
// If none is found, just return T
|
||||
|
||||
using variant_type = Variant;
|
||||
using types = typename variant_type::types;
|
||||
using end = typename mpl::end<types>::type;
|
||||
typedef Variant variant_type;
|
||||
typedef typename variant_type::types types;
|
||||
typedef typename mpl::end<types>::type end;
|
||||
|
||||
using iter_1 = typename mpl::find<types, T>::type;
|
||||
typedef typename mpl::find<types, T>::type iter_1;
|
||||
|
||||
using iter = typename mpl::eval_if<
|
||||
std::is_same<iter_1, end>,
|
||||
mpl::find_if<types, traits::is_substitute<T, mpl::_1> >,
|
||||
std::type_identity<iter_1>
|
||||
>::type;
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<iter_1, end>,
|
||||
mpl::find_if<types, traits::is_substitute<T, mpl::_1> >,
|
||||
mpl::identity<iter_1>
|
||||
>::type
|
||||
iter;
|
||||
|
||||
using type = typename mpl::eval_if<
|
||||
std::is_same<iter, end>,
|
||||
std::type_identity<T>,
|
||||
mpl::deref<iter>
|
||||
>::type;
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<iter, end>,
|
||||
mpl::identity<T>,
|
||||
mpl::deref<iter>
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template <typename Variant, typename T>
|
||||
using variant_find_substitute_t = typename variant_find_substitute<Variant, T>::type;
|
||||
|
||||
|
||||
template <typename Variant>
|
||||
struct variant_find_substitute<Variant, Variant>
|
||||
{
|
||||
using type = Variant;
|
||||
};
|
||||
: mpl::identity<Variant> {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2025 Nana Sakisaka
|
||||
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)
|
||||
@@ -9,49 +9,43 @@
|
||||
#define BOOST_SPIRIT_X3_VARIANT_HAS_SUBSTITUTE_APR_18_2014_925AM
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
|
||||
#include <boost/mpl/find.hpp> // TODO: remove this
|
||||
#include <boost/mpl/find.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost::spirit::x3::traits
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
namespace detail
|
||||
template <typename Variant, typename T>
|
||||
struct variant_has_substitute_impl
|
||||
{
|
||||
template <typename Variant, typename T>
|
||||
struct variant_has_substitute_impl
|
||||
{
|
||||
// Find a type from the Variant that can be a substitute for T.
|
||||
// return true_ if one is found, else false_
|
||||
// Find a type from the Variant that can be a substitute for T.
|
||||
// return true_ if one is found, else false_
|
||||
|
||||
using variant_type = Variant;
|
||||
using types = typename variant_type::types;
|
||||
using end = typename mpl::end<types>::type;
|
||||
using iter_1 = typename mpl::find<types, T>::type;
|
||||
typedef Variant variant_type;
|
||||
typedef typename variant_type::types types;
|
||||
typedef typename mpl::end<types>::type end;
|
||||
|
||||
using iter = typename mpl::eval_if<
|
||||
std::is_same<iter_1, end>,
|
||||
typedef typename mpl::find<types, T>::type iter_1;
|
||||
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<iter_1, end>,
|
||||
mpl::find_if<types, traits::is_substitute<T, mpl::_1>>,
|
||||
std::type_identity<iter_1>
|
||||
>::type;
|
||||
mpl::identity<iter_1>
|
||||
>::type
|
||||
iter;
|
||||
|
||||
using type = std::bool_constant<!std::is_same_v<iter, end>>;
|
||||
};
|
||||
} // detail
|
||||
typedef mpl::not_<is_same<iter, end>> type;
|
||||
};
|
||||
|
||||
template <typename Variant, typename T>
|
||||
struct variant_has_substitute
|
||||
: detail::variant_has_substitute_impl<Variant, T>::type
|
||||
{};
|
||||
|
||||
template <typename Variant, typename T>
|
||||
constexpr bool variant_has_substitute_v = variant_has_substitute<Variant, T>::value;
|
||||
: variant_has_substitute_impl<Variant, T>::type {};
|
||||
|
||||
template <typename T>
|
||||
struct variant_has_substitute<unused_type, T> : std::true_type {};
|
||||
struct variant_has_substitute<unused_type, T> : mpl::true_ {};
|
||||
|
||||
template <typename T>
|
||||
struct variant_has_substitute<unused_type const, T> : std::true_type {};
|
||||
struct variant_has_substitute<unused_type const, T> : mpl::true_ {};
|
||||
|
||||
} // boost::spirit::x3::traits
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2017-2021 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
/*=============================================================================
|
||||
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)
|
||||
=============================================================================*/
|
||||
#include "test.hpp"
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/fusion/include/std_pair.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "test.hpp"
|
||||
|
||||
using boost::spirit::x3::rule;
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2012 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
#include <boost/fusion/include/std_pair.hpp>
|
||||
@@ -17,6 +14,7 @@
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include "test.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// bogus https://developercommunity.visualstudio.com/t/buggy-warning-c4709/471956
|
||||
@@ -36,10 +34,9 @@ struct f
|
||||
};
|
||||
|
||||
|
||||
struct stationary
|
||||
struct stationary : boost::noncopyable
|
||||
{
|
||||
explicit stationary(int i) : val{i} {}
|
||||
stationary(stationary const&) = delete;
|
||||
stationary& operator=(int i) { val = i; return *this; }
|
||||
|
||||
int val;
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
/*=============================================================================
|
||||
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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include "test.hpp"
|
||||
|
||||
namespace x3 = boost::spirit::x3;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user