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

Modernize x3::raw

This commit is contained in:
Nana Sakisaka
2025-09-10 10:41:59 +09:00
parent 495f936af2
commit b232c5abc0
2 changed files with 63 additions and 34 deletions

View File

@@ -1,5 +1,6 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2014 Joel de Guzman Copyright (c) 2014 Joel de Guzman
Copyright (c) 2025 Nana Sakisaka
Distributed under the Boost Software License, Version 1.0. (See accompanying 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) file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,11 +12,20 @@
#include <boost/spirit/home/x3/core/parser.hpp> #include <boost/spirit/home/x3/core/parser.hpp>
#include <boost/spirit/home/x3/support/traits/move_to.hpp> #include <boost/spirit/home/x3/support/traits/move_to.hpp>
#include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp> #include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp>
#include <boost/range/iterator_range_core.hpp>
namespace boost { namespace spirit { namespace x3 #ifndef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
# pragma message("Use of `boost::iterator_range` is deprecated in X3. #define BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE")
# include <boost/range/iterator_range_core.hpp>
#endif
#include <ranges>
#include <iterator>
#include <type_traits>
#include <utility>
namespace boost::spirit::x3
{ {
// this is a pseudo attribute type indicating that the parser wants the // Pseudo attribute type indicating that the parser wants the
// iterator range pointing to the [first, last) matching characters from // iterator range pointing to the [first, last) matching characters from
// the input iterators. // the input iterators.
struct raw_attribute_type {}; struct raw_attribute_type {};
@@ -23,64 +33,83 @@ namespace boost { namespace spirit { namespace x3
template <typename Subject> template <typename Subject>
struct raw_directive : unary_parser<Subject, raw_directive<Subject>> struct raw_directive : unary_parser<Subject, raw_directive<Subject>>
{ {
typedef unary_parser<Subject, raw_directive<Subject> > base_type; using base_type = unary_parser<Subject, raw_directive<Subject>>;
typedef raw_attribute_type attribute_type; using attribute_type = raw_attribute_type;
static bool const handles_container = true; using subject_type = Subject;
typedef Subject subject_type;
constexpr raw_directive(Subject const& subject) static constexpr bool handles_container = true;
: base_type(subject) {}
template <typename Iterator, typename Context template <typename SubjectT>
, typename RContext, typename Attribute> requires std::is_constructible_v<Subject, SubjectT>
bool parse(Iterator& first, Iterator const& last constexpr raw_directive(SubjectT&& subject)
, Context const& context, RContext& rcontext, Attribute& attr) const noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
: base_type(std::forward<SubjectT>(subject))
{}
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext, typename Attribute>
[[nodiscard]] constexpr bool
parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const
// never noexcept; construction of `std::ranges::subrange` is never noexcept
{ {
static_assert(Parsable<Subject, It, Se, Context, RContext, unused_type>);
x3::skip_over(first, last, context); x3::skip_over(first, last, context);
Iterator i = first; It local_it = first;
if (this->subject.parse(i, last, context, rcontext, unused)) if (this->subject.parse(local_it, last, context, rcontext, unused))
{ {
traits::move_to(first, i, attr); traits::move_to(first, local_it, attr);
first = i; first = local_it;
return true; return true;
} }
return false; return false;
} }
template <typename Iterator, typename Context, typename RContext> template <std::forward_iterator It, std::sentinel_for<It> Se, typename Context, typename RContext>
bool parse(Iterator& first, Iterator const& last [[nodiscard]] constexpr bool
, Context const& context, RContext& rcontext, unused_type) const parse(It& first, Se const& last, Context const& context, RContext& rcontext, unused_type) const
noexcept(is_nothrow_parsable_v<Subject, It, Se, Context, RContext, unused_type>)
{ {
return this->subject.parse(first, last, context, rcontext, unused); return this->subject.parse(first, last, context, rcontext, unused);
} }
}; };
struct raw_gen namespace detail
{ {
template <typename Subject> struct raw_gen
constexpr raw_directive<typename extension::as_parser<Subject>::value_type>
operator[](Subject const& subject) const
{ {
return { as_parser(subject) }; template <X3Subject Subject>
} [[nodiscard]] constexpr raw_directive<as_parser_plain_t<Subject>>
}; operator[](Subject&& subject) const
noexcept(is_parser_nothrow_constructible_v<raw_directive<as_parser_plain_t<Subject>>, as_parser_t<Subject>>)
{
return { as_parser(std::forward<Subject>(subject)) };
}
};
} // detail
constexpr auto raw = raw_gen{}; inline namespace cpos
{
inline constexpr detail::raw_gen raw{};
}
namespace traits namespace traits
{ {
template <typename Context, typename Iterator> template <typename Context, std::forward_iterator It>
struct pseudo_attribute<Context, raw_attribute_type, Iterator> struct pseudo_attribute<Context, raw_attribute_type, It>
{ {
using attribute_type = raw_attribute_type; using attribute_type = raw_attribute_type;
using type = boost::iterator_range<Iterator>; #ifdef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
using type = std::ranges::subrange<It>;
#else
using type = boost::iterator_range<It>;
#endif
static type call(Iterator& first, Iterator const& last, attribute_type) [[nodiscard]] static constexpr type call(It& first, std::sentinel_for<It> auto const& last, raw_attribute_type)
{ {
return { first, last }; return { first, last };
} }
}; };
} }
}}} } // boost::spirit::x3
#endif #endif

View File

@@ -29,7 +29,7 @@ int main()
{ {
using spirit_test::test; using spirit_test::test;
using spirit_test::test_attr; using spirit_test::test_attr;
using namespace boost::spirit::x3::ascii; using namespace boost::spirit::x3::standard;
using boost::spirit::x3::raw; using boost::spirit::x3::raw;
using boost::spirit::x3::eps; using boost::spirit::x3::eps;
using boost::spirit::x3::lit; using boost::spirit::x3::lit;