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:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user