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

Modernize x3::expect

This commit is contained in:
Nana Sakisaka
2025-09-10 08:49:55 +09:00
parent b6acdc57d3
commit f52dae0d2c
2 changed files with 61 additions and 40 deletions

View File

@@ -1,7 +1,7 @@
/*=============================================================================
Copyright (c) 2001-2014 Joel de Guzman
Copyright (c) 2017 wanghan02
Copyright (c) 2024 Nana Sakisaka
Copyright (c) 2024-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)
@@ -14,21 +14,30 @@
#include <boost/spirit/home/x3/core/parser.hpp>
#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
namespace boost { namespace spirit { namespace x3
#include <iterator>
#include <type_traits>
#include <utility>
namespace boost::spirit::x3
{
template <typename Subject>
struct expect_directive : unary_parser<Subject, expect_directive<Subject>>
{
typedef unary_parser<Subject, expect_directive<Subject> > base_type;
static bool const is_pass_through_unary = true;
using base_type = unary_parser<Subject, expect_directive<Subject>>;
static constexpr bool is_pass_through_unary = true;
constexpr expect_directive(Subject const& subject)
: base_type(subject) {}
template <typename SubjectT>
requires std::is_constructible_v<Subject, SubjectT>
constexpr expect_directive(SubjectT&& subject)
noexcept(std::is_nothrow_constructible_v<Subject, SubjectT>)
: base_type(std::forward<SubjectT>(subject))
{}
template <typename Iterator, typename Context
, typename RContext, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr) const
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; expectation failure requires construction of debug information
{
bool const r = this->subject.parse(first, last, context, rcontext, attr);
@@ -36,12 +45,12 @@ namespace boost { namespace spirit { namespace x3
{
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
boost::throw_exception(
expectation_failure<Iterator>(
first, what(this->subject)));
expectation_failure<It>(
first, x3::what(this->subject)));
#else
if (!has_expectation_failure(context))
if (!x3::has_expectation_failure(context))
{
set_expectation_failure(first, this->subject, context);
x3::set_expectation_failure(first, this->subject, context);
}
#endif
}
@@ -49,50 +58,59 @@ namespace boost { namespace spirit { namespace x3
}
};
struct expect_gen
namespace detail
{
template <typename Subject>
constexpr expect_directive<typename extension::as_parser<Subject>::value_type>
operator[](Subject const& subject) const
struct expect_gen
{
return { as_parser(subject) };
}
};
template <X3Subject Subject>
[[nodiscard]] constexpr expect_directive<as_parser_plain_t<Subject>>
operator[](Subject&& subject) const
noexcept(is_parser_nothrow_constructible_v<expect_directive<as_parser_plain_t<Subject>>, Subject>)
{
return { as_parser(std::forward<Subject>(subject)) };
}
};
} // detail
constexpr auto expect = expect_gen{};
}}}
inline namespace cpos
{
inline constexpr detail::expect_gen expect{};
} // cpos
namespace boost { namespace spirit { namespace x3 { namespace detail
} // boost::spirit::x3
namespace boost::spirit::x3::detail
{
// Special case handling for expect expressions.
template <typename Subject, typename Context, typename RContext>
struct parse_into_container_impl<expect_directive<Subject>, Context, RContext>
{
template <typename Iterator, typename Attribute>
static bool call(
expect_directive<Subject> const& parser
, Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr)
template <std::forward_iterator It, std::sentinel_for<It> Se, typename Attribute>
[[nodiscard]] static constexpr bool
call(
expect_directive<Subject> const& parser,
It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr
) // never noexcept; expectation failure requires construction of debug information
{
bool const r = parse_into_container(
bool const r = detail::parse_into_container(
parser.subject, first, last, context, rcontext, attr);
if (!r)
{
#if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
boost::throw_exception(
expectation_failure<Iterator>(
first, what(parser.subject)));
expectation_failure<It>(
first, x3::what(parser.subject)));
#else
if (!has_expectation_failure(context))
if (!x3::has_expectation_failure(context))
{
set_expectation_failure(first, parser.subject, context);
x3::set_expectation_failure(first, parser.subject, context);
}
#endif
}
return r;
}
};
}}}}
} // boost::spirit::x3::detail
#endif

View File

@@ -1,11 +1,14 @@
/*=============================================================================
Copyright (c) 2001-2013 Joel de Guzman
Copyright (c) 2017 wanghan02
Copyright (c) 2024 Nana Sakisaka
Copyright (c) 2024-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)
=============================================================================*/
#define BOOST_SPIRIT_X3_USE_BOOST_OPTIONAL 0
#define BOOST_SPIRIT_X3_NO_BOOST_ITERATOR_RANGE
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/binary.hpp>
#include <boost/spirit/home/x3/directive/with.hpp>
@@ -262,10 +265,10 @@ int TEST_MAIN_FUNC()
using x3::eps;
using x3::eoi;
using x3::eol;
using x3::attr;
//using x3::attr;
using x3::dword;
using x3::int_;
using x3::symbols;
using x3::shared_symbols;
using x3::confix;
using x3::with;
using x3::expectation_failure;
@@ -488,7 +491,7 @@ int TEST_MAIN_FUNC()
});
int n = 0;
TEST_ATTR_SUCCESS_PASS("abc", lit("abc") > attr(12) > eoi, n);
TEST_ATTR_SUCCESS_PASS("abc", lit("abc") > x3::attr(12) > eoi, n);
BOOST_TEST(n == 12);
}
@@ -509,7 +512,7 @@ int TEST_MAIN_FUNC()
BOOST_TEST(x.where() == "a"sv);
});
symbols<> s;
shared_symbols<> s;
s.add("cat");
TEST_SUCCESS_PASS("12cat", +digit > s);
TEST_FAILURE("12dog", +digit > s, {