From b232c5abc00e3df04633105a0599782842d7b2bc Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Wed, 10 Sep 2025 10:41:59 +0900 Subject: [PATCH] Modernize `x3::raw` --- .../boost/spirit/home/x3/directive/raw.hpp | 95 ++++++++++++------- test/x3/raw.cpp | 2 +- 2 files changed, 63 insertions(+), 34 deletions(-) diff --git a/include/boost/spirit/home/x3/directive/raw.hpp b/include/boost/spirit/home/x3/directive/raw.hpp index 2914eb921..ddd66bdb7 100644 --- a/include/boost/spirit/home/x3/directive/raw.hpp +++ b/include/boost/spirit/home/x3/directive/raw.hpp @@ -1,5 +1,6 @@ /*============================================================================= Copyright (c) 2014 Joel de Guzman + Copyright (c) 2025 Nana Sakisaka Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -11,11 +12,20 @@ #include #include #include -#include -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 +#endif + +#include +#include +#include +#include + +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 // the input iterators. struct raw_attribute_type {}; @@ -23,64 +33,83 @@ namespace boost { namespace spirit { namespace x3 template struct raw_directive : unary_parser> { - typedef unary_parser > base_type; - typedef raw_attribute_type attribute_type; - static bool const handles_container = true; - typedef Subject subject_type; + using base_type = unary_parser>; + using attribute_type = raw_attribute_type; + using subject_type = Subject; - constexpr raw_directive(Subject const& subject) - : base_type(subject) {} + static constexpr bool handles_container = true; - template - bool parse(Iterator& first, Iterator const& last - , Context const& context, RContext& rcontext, Attribute& attr) const + template + requires std::is_constructible_v + constexpr raw_directive(SubjectT&& subject) + noexcept(std::is_nothrow_constructible_v) + : base_type(std::forward(subject)) + {} + + template 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); + x3::skip_over(first, last, context); - Iterator i = first; - if (this->subject.parse(i, last, context, rcontext, unused)) + It local_it = first; + if (this->subject.parse(local_it, last, context, rcontext, unused)) { - traits::move_to(first, i, attr); - first = i; + traits::move_to(first, local_it, attr); + first = local_it; return true; } return false; } - template - bool parse(Iterator& first, Iterator const& last - , Context const& context, RContext& rcontext, unused_type) const + template Se, typename Context, typename RContext> + [[nodiscard]] constexpr bool + parse(It& first, Se const& last, Context const& context, RContext& rcontext, unused_type) const + noexcept(is_nothrow_parsable_v) { return this->subject.parse(first, last, context, rcontext, unused); } }; - struct raw_gen + namespace detail { - template - constexpr raw_directive::value_type> - operator[](Subject const& subject) const + struct raw_gen { - return { as_parser(subject) }; - } - }; + template + [[nodiscard]] constexpr raw_directive> + operator[](Subject&& subject) const + noexcept(is_parser_nothrow_constructible_v>, as_parser_t>) + { + return { as_parser(std::forward(subject)) }; + } + }; + } // detail - constexpr auto raw = raw_gen{}; + inline namespace cpos + { + inline constexpr detail::raw_gen raw{}; + } namespace traits { - template - struct pseudo_attribute + template + struct pseudo_attribute { using attribute_type = raw_attribute_type; - using type = boost::iterator_range; + #ifdef BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE + using type = std::ranges::subrange; + #else + using type = boost::iterator_range; + #endif - static type call(Iterator& first, Iterator const& last, attribute_type) + [[nodiscard]] static constexpr type call(It& first, std::sentinel_for auto const& last, raw_attribute_type) { return { first, last }; } }; } -}}} +} // boost::spirit::x3 #endif diff --git a/test/x3/raw.cpp b/test/x3/raw.cpp index eed193f9e..9fe2bc909 100644 --- a/test/x3/raw.cpp +++ b/test/x3/raw.cpp @@ -29,7 +29,7 @@ int main() { using spirit_test::test; 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::eps; using boost::spirit::x3::lit;