2
0
mirror of https://github.com/boostorg/spirit.git synced 2026-01-19 04:42:11 +00:00

Revert "Merge pull request #821 from saki7/modernize-lexeme"

This reverts commit b86852dd88, reversing
changes made to b389b1ce56.
This commit is contained in:
Nana Sakisaka
2025-09-13 08:57:03 +09:00
parent 26d6ec1a64
commit bc3138da91
3 changed files with 93 additions and 135 deletions

View File

@@ -1,7 +1,7 @@
/*=============================================================================
Copyright (c) 2001-2014 Joel de Guzman
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)
@@ -13,86 +13,61 @@
#include <boost/spirit/home/x3/support/unused.hpp>
#include <boost/spirit/home/x3/support/context.hpp>
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/declval.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/spirit/home/x3/core/parser.hpp>
#include <iterator>
#include <type_traits>
namespace boost::spirit::x3
namespace boost { namespace spirit { namespace x3
{
// Tag used to find the skipper from the context
struct skipper_tag;
///////////////////////////////////////////////////////////////////////////
// Move the /first/ iterator to the first non-matching position
// given a skip-parser. The function is a no-op if unused_type or
// unused_skipper is passed as the skip-parser.
template <X3Subject Skipper>
struct [[nodiscard]] unused_skipper
///////////////////////////////////////////////////////////////////////////
template <typename Skipper>
struct unused_skipper : unused_type
{
constexpr unused_skipper(Skipper const& skipper) noexcept
: skipper(skipper)
{}
unused_skipper(Skipper const& skipper)
: skipper(skipper) {}
Skipper const& skipper;
};
template <typename Context>
using unused_skipper_t = unused_skipper<std::remove_cvref_t<decltype(x3::get<skipper_tag>(std::declval<Context>()))>>;
namespace detail
{
template <typename Skipper>
struct is_unused_skipper : std::false_type
{
static_assert(X3Subject<Skipper>);
};
struct is_unused_skipper
: mpl::false_ {};
template <typename Skipper>
struct is_unused_skipper<unused_skipper<Skipper>> : std::true_type {};
struct is_unused_skipper<unused_skipper<Skipper>>
: mpl::true_ {};
template <>
struct is_unused_skipper<unused_type> : std::true_type {};
struct is_unused_skipper<unused_type>
: mpl::true_ {};
template <typename Skipper>
[[nodiscard]] constexpr Skipper const&
get_unused_skipper(Skipper const& skipper) noexcept
inline Skipper const&
get_unused_skipper(Skipper const& skipper)
{
static_assert(X3Subject<Skipper>);
return skipper;
}
template <typename Skipper>
[[nodiscard]] constexpr Skipper const&
get_unused_skipper(unused_skipper<Skipper> const& unused_skipper) noexcept
inline Skipper const&
get_unused_skipper(unused_skipper<Skipper> const& unused_skipper)
{
static_assert(X3Subject<Skipper>);
return unused_skipper.skipper;
}
template <typename Context>
struct skip_over_context
{
using type = unused_type;
};
template <typename Context>
requires (!std::is_same_v<expectation_failure_t<Context>, unused_type>)
struct skip_over_context<Context>
{
using type = std::remove_cvref_t<decltype(x3::make_context<expectation_failure_tag>(
x3::get<expectation_failure_tag>(std::declval<Context const&>())
))>;
};
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, X3Subject Skipper>
constexpr void skip_over(
It& first, Se const& last, Context& context, Skipper const& skipper
)
noexcept(is_nothrow_parsable_v<Skipper, It, Se, typename skip_over_context<Context>::type, unused_type, unused_type>)
template <typename Iterator, typename Context, typename Skipper>
inline void skip_over(
Iterator& first, Iterator const& last, Context& context, Skipper const& skipper)
{
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
(void)context;
boost::ignore_unused(context);
while (skipper.parse(first, last, unused, unused, unused))
/* loop */;
#else
@@ -142,7 +117,7 @@ namespace boost::spirit::x3
// For this reason we're going to cherry-pick the reference
// and repack it into a brand new context.
auto const local_ctx = x3::make_context<expectation_failure_tag>(
auto const local_ctx = make_context<expectation_failure_tag>(
x3::get<expectation_failure_tag>(context));
while (skipper.parse(first, last, local_ctx, unused, unused))
@@ -151,33 +126,35 @@ namespace boost::spirit::x3
#endif
}
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context>
constexpr void skip_over(It&, Se const&, Context&, unused_type) noexcept
template <typename Iterator, typename Context>
inline void skip_over(Iterator&, Iterator const&, Context&, unused_type)
{
}
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename Skipper>
constexpr void skip_over(It&, Se const&, Context&, unused_skipper<Skipper> const&) noexcept
template <typename Iterator, typename Context, typename Skipper>
inline void skip_over(
Iterator&, Iterator const&, Context&, unused_skipper<Skipper> const&)
{
}
}
// this tag is used to find the skipper from the context
struct skipper_tag;
template <typename Context>
struct has_skipper
: std::bool_constant<!detail::is_unused_skipper<
std::remove_cvref_t<decltype(x3::get<skipper_tag>(std::declval<Context>()))>
>::value>
{};
: mpl::not_<detail::is_unused_skipper<
typename remove_cv<typename remove_reference<
decltype(x3::get<skipper_tag>(boost::declval<Context>()))
>::type>::type
>> {};
template <typename Context>
constexpr bool has_skipper_v = has_skipper<Context>::value;
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context>
constexpr void skip_over(It& first, Se const& last, Context& context)
noexcept(noexcept(detail::skip_over(first, last, context, x3::get<skipper_tag>(context))))
template <typename Iterator, typename Context>
inline void skip_over(
Iterator& first, Iterator const& last, Context& context)
{
detail::skip_over(first, last, context, x3::get<skipper_tag>(context));
}
} // boost::spirit::x3
}}}
#endif

View File

@@ -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)
@@ -12,85 +11,68 @@
#include <boost/spirit/home/x3/support/unused.hpp>
#include <boost/spirit/home/x3/core/skip_over.hpp>
#include <boost/spirit/home/x3/core/parser.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
#include <iterator>
#include <type_traits>
#include <utility>
namespace boost::spirit::x3
namespace boost { namespace spirit { namespace x3
{
template <typename Subject>
struct lexeme_directive : unary_parser<Subject, lexeme_directive<Subject>>
{
using base_type = unary_parser<Subject, lexeme_directive<Subject>>;
static constexpr bool is_pass_through_unary = true;
static constexpr bool handles_container = Subject::handles_container;
typedef unary_parser<Subject, lexeme_directive<Subject> > base_type;
static bool const is_pass_through_unary = true;
static bool const handles_container = Subject::handles_container;
template <typename SubjectT>
requires std::is_constructible_v<Subject, SubjectT>
constexpr lexeme_directive(SubjectT&& subject)
noexcept(std::is_nothrow_constructible_v<base_type, SubjectT>)
: base_type(std::forward<SubjectT>(subject))
{}
constexpr lexeme_directive(Subject const& subject)
: base_type(subject) {}
template <typename Context>
using pre_skip_context_t = std::remove_cvref_t<decltype(
x3::make_context<skipper_tag>(std::declval<unused_skipper_t<Context>&>(), std::declval<Context const&>())
)>;
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
requires has_skipper_v<Context>
[[nodiscard]] constexpr bool parse(
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
) const
noexcept(
noexcept(x3::skip_over(first, last, context)) &&
is_nothrow_parsable_v<Subject, It, Se, pre_skip_context_t<Context>, RContext, Attribute>
)
template <typename Iterator, typename Context
, typename RContext, typename Attribute>
typename enable_if<has_skipper<Context>, bool>::type
parse(Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr) const
{
x3::skip_over(first, last, context);
auto const& skipper = x3::get<skipper_tag>(context);
unused_skipper_t<Context> unused_skipper(skipper);
typedef unused_skipper<
typename remove_reference<decltype(skipper)>::type>
unused_skipper_type;
unused_skipper_type unused_skipper(skipper);
return this->subject.parse(
first, last,
x3::make_context<skipper_tag>(unused_skipper, context),
rcontext,
attr
);
first, last
, make_context<skipper_tag>(unused_skipper, context)
, rcontext
, attr);
}
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
requires (!has_skipper_v<Context>)
[[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>)
template <typename Iterator, typename Context
, typename RContext, typename Attribute>
typename disable_if<has_skipper<Context>, bool>::type
parse(Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr) const
{
// no need to pre-skip if skipper is unused
return this->subject.parse(first, last, context, rcontext, attr);
return this->subject.parse(
first, last
, context
, rcontext
, attr);
}
};
namespace detail
struct lexeme_gen
{
struct lexeme_gen
template <typename Subject>
constexpr lexeme_directive<typename extension::as_parser<Subject>::value_type>
operator[](Subject const& subject) const
{
template <X3Subject Subject>
[[nodiscard]] constexpr lexeme_directive<as_parser_plain_t<Subject>>
operator[](Subject&& subject) const
noexcept(is_parser_nothrow_constructible_v<lexeme_directive<as_parser_plain_t<Subject>>, Subject>)
{
return { as_parser(std::forward<Subject>(subject)) };
}
};
} // detail
return { as_parser(subject) };
}
};
inline namespace cpos
{
inline constexpr detail::lexeme_gen lexeme{};
}
} // boost::spirit::x3
constexpr auto lexeme = lexeme_gen{};
}}}
#endif

View File

@@ -1,22 +1,21 @@
/*=============================================================================
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 <iostream>
#include "test.hpp"
int main()
int
main()
{
using spirit_test::test;
using boost::spirit::x3::standard::space;
using boost::spirit::x3::standard::space_type;
using boost::spirit::x3::standard::digit;
using boost::spirit::x3::ascii::space;
using boost::spirit::x3::ascii::space_type;
using boost::spirit::x3::ascii::digit;
using boost::spirit::x3::lexeme;
using boost::spirit::x3::rule;