File indexing completed on 2025-09-13 08:51:46
0001
0002
0003
0004
0005
0006
0007
0008 #if !defined(BOOST_SPIRIT_X3_SUPPORT_EXPECTATION_HPP)
0009 #define BOOST_SPIRIT_X3_SUPPORT_EXPECTATION_HPP
0010
0011 #if !defined(BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE)
0012 # define BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE 1
0013 #endif
0014
0015 #include <boost/config.hpp> // for BOOST_SYMBOL_VISIBLE, BOOST_ATTRIBUTE_NODISCARD
0016 #include <boost/core/ignore_unused.hpp>
0017 #include <boost/spirit/home/x3/support/unused.hpp>
0018 #include <boost/spirit/home/x3/support/context.hpp>
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <boost/spirit/home/x3/support/traits/optional_traits.hpp>
0035
0036
0037
0038
0039 #include <boost/optional.hpp>
0040 #include <optional>
0041
0042 #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0043 # define BOOST_SPIRIT_X3_EXPECTATION_FAILURE_API BOOST_SYMBOL_VISIBLE
0044 # define BOOST_SPIRIT_X3_EXPECTATION_FAILURE_BASE : std::runtime_error
0045 # define BOOST_SPIRIT_X3_EXPECTATION_FAILURE_NS throwing
0046 # include <boost/throw_exception.hpp>
0047 # include <stdexcept>
0048
0049 #else
0050 # define BOOST_SPIRIT_X3_EXPECTATION_FAILURE_API
0051 # define BOOST_SPIRIT_X3_EXPECTATION_FAILURE_BASE
0052 # define BOOST_SPIRIT_X3_EXPECTATION_FAILURE_NS non_throwing
0053 #endif
0054
0055 #include <string>
0056 #include <type_traits>
0057
0058
0059 namespace boost { namespace spirit { namespace x3
0060 {
0061 struct expectation_failure_tag;
0062
0063 inline namespace BOOST_SPIRIT_X3_EXPECTATION_FAILURE_NS
0064 {
0065 template <typename Iterator>
0066 struct BOOST_SPIRIT_X3_EXPECTATION_FAILURE_API
0067 expectation_failure BOOST_SPIRIT_X3_EXPECTATION_FAILURE_BASE
0068 {
0069 public:
0070 expectation_failure(Iterator where, std::string const& which)
0071 #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0072 : std::runtime_error("boost::spirit::x3::expectation_failure"),
0073 #else
0074 :
0075 #endif
0076 where_(where), which_(which)
0077 {}
0078
0079 BOOST_ATTRIBUTE_NODISCARD
0080 constexpr Iterator const& where() const noexcept { return where_; }
0081
0082 BOOST_ATTRIBUTE_NODISCARD
0083 constexpr std::string const& which() const noexcept { return which_; }
0084
0085 private:
0086 Iterator where_;
0087 std::string which_;
0088 };
0089
0090
0091 template <typename Context>
0092 using expectation_failure_t = std::remove_cv_t<std::remove_reference_t<
0093 decltype(x3::get<expectation_failure_tag>(std::declval<Context>()))>>;
0094
0095 template <typename Iterator>
0096 using expectation_failure_optional =
0097 typename traits::build_optional<expectation_failure<Iterator>>::type;
0098
0099
0100
0101
0102
0103
0104
0105
0106 namespace expectation_failure_helpers
0107 {
0108
0109 template <typename Iterator>
0110 BOOST_ATTRIBUTE_NODISCARD
0111 constexpr decltype(auto) where(expectation_failure<Iterator> const& failure) noexcept { return failure.where(); }
0112
0113 template <typename Iterator>
0114 BOOST_ATTRIBUTE_NODISCARD
0115 constexpr decltype(auto) which(expectation_failure<Iterator> const& failure) noexcept { return failure.which(); }
0116
0117
0118 template <typename Iterator>
0119 BOOST_ATTRIBUTE_NODISCARD
0120 constexpr decltype(auto) where(std::optional<expectation_failure<Iterator>> const& failure) noexcept { return failure->where(); }
0121
0122 template <typename Iterator>
0123 BOOST_ATTRIBUTE_NODISCARD
0124 constexpr decltype(auto) which(std::optional<expectation_failure<Iterator>> const& failure) noexcept { return failure->which(); }
0125
0126
0127 template <typename Iterator>
0128 BOOST_ATTRIBUTE_NODISCARD
0129 constexpr decltype(auto) where(boost::optional<expectation_failure<Iterator>> const& failure) noexcept { return failure->where(); }
0130
0131 template <typename Iterator>
0132 BOOST_ATTRIBUTE_NODISCARD
0133 constexpr decltype(auto) which(boost::optional<expectation_failure<Iterator>> const& failure) noexcept { return failure->which(); }
0134
0135
0136 template <typename Iterator>
0137 BOOST_ATTRIBUTE_NODISCARD
0138 constexpr decltype(auto) where(std::reference_wrapper<std::optional<expectation_failure<Iterator>>> const& failure) noexcept { return failure.get()->where(); }
0139
0140 template <typename Iterator>
0141 BOOST_ATTRIBUTE_NODISCARD
0142 constexpr decltype(auto) which(std::reference_wrapper<std::optional<expectation_failure<Iterator>>> const& failure) noexcept { return failure.get()->which(); }
0143
0144
0145 template <typename Iterator>
0146 BOOST_ATTRIBUTE_NODISCARD
0147 constexpr decltype(auto) where(std::reference_wrapper<boost::optional<expectation_failure<Iterator>>> const& failure) noexcept { return failure.get()->where(); }
0148
0149 template <typename Iterator>
0150 BOOST_ATTRIBUTE_NODISCARD
0151 constexpr decltype(auto) which(std::reference_wrapper<boost::optional<expectation_failure<Iterator>>> const& failure) noexcept { return failure.get()->which(); }
0152 }
0153
0154 using expectation_failure_helpers::where;
0155 using expectation_failure_helpers::which;
0156
0157 }
0158
0159 #if !BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0160 namespace detail {
0161 inline namespace BOOST_SPIRIT_X3_EXPECTATION_FAILURE_NS
0162 {
0163 inline constexpr bool has_expectation_failure_impl(unused_type const&) noexcept = delete;
0164
0165 inline constexpr bool has_expectation_failure_impl(bool& failure) noexcept {
0166 return failure;
0167 }
0168
0169 template <typename Iterator>
0170 constexpr bool has_expectation_failure_impl(std::optional<expectation_failure<Iterator>> const& failure) noexcept
0171 {
0172 return failure.has_value();
0173 }
0174
0175 template <typename Iterator>
0176 constexpr bool has_expectation_failure_impl(boost::optional<expectation_failure<Iterator>> const& failure) noexcept
0177 {
0178 return failure.has_value();
0179 }
0180
0181 template <typename T>
0182 constexpr bool has_expectation_failure_impl(std::reference_wrapper<T> const& ref) noexcept
0183 {
0184 return has_expectation_failure_impl(ref.get());
0185 }
0186
0187
0188 template <typename Iterator, typename T>
0189 constexpr void set_expectation_failure_impl(bool& failure, T&& value)
0190 {
0191 failure = std::forward<T>(value);
0192 }
0193
0194 template <typename Iterator, typename T>
0195 constexpr void set_expectation_failure_impl(std::optional<expectation_failure<Iterator>>& failure, T&& value)
0196 {
0197 failure = std::forward<T>(value);
0198 }
0199
0200 template <typename Iterator, typename T>
0201 constexpr void set_expectation_failure_impl(boost::optional<expectation_failure<Iterator>>& failure, T&& value)
0202 {
0203 failure = std::forward<T>(value);
0204 }
0205
0206 template <typename AnyExpectationFailure, typename T>
0207 constexpr void set_expectation_failure_impl(std::reference_wrapper<AnyExpectationFailure>& failure, T&& value)
0208 {
0209 set_expectation_failure_impl(failure.get(), std::forward<T>(value));
0210 }
0211
0212
0213 template <typename Iterator>
0214 constexpr void clear_expectation_failure_impl(unused_type const&) noexcept = delete;
0215
0216 template <typename Iterator>
0217 constexpr void clear_expectation_failure_impl(bool& failure) noexcept
0218 {
0219 failure = false;
0220 }
0221
0222 template <typename Iterator>
0223 constexpr void clear_expectation_failure_impl(std::optional<expectation_failure<Iterator>>& failure) noexcept
0224 {
0225 failure.reset();
0226 }
0227
0228 template <typename Iterator>
0229 constexpr void clear_expectation_failure_impl(boost::optional<expectation_failure<Iterator>>& failure) noexcept
0230 {
0231 failure.reset();
0232 }
0233
0234 template <typename T>
0235 constexpr void clear_expectation_failure_impl(std::reference_wrapper<T>& ref) noexcept
0236 {
0237 return clear_expectation_failure_impl(ref.get());
0238 }
0239 }
0240 }
0241 #endif
0242
0243 inline namespace BOOST_SPIRIT_X3_EXPECTATION_FAILURE_NS
0244 {
0245 template <typename Context>
0246 BOOST_ATTRIBUTE_NODISCARD
0247 constexpr bool has_expectation_failure(Context const& context) noexcept {
0248 #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0249 boost::ignore_unused(context);
0250 return false;
0251 #else
0252 using T = expectation_failure_t<Context>;
0253 static_assert(
0254 !std::is_same_v<unused_type, T>,
0255 "Context type was not specified for x3::expectation_failure_tag. "
0256 "You probably forgot: `x3::with<x3::expectation_failure_tag>(failure)[p]`. "
0257 "Note that you must also bind the context to your skipper."
0258 );
0259 return detail::has_expectation_failure_impl(
0260 x3::get<expectation_failure_tag>(context));
0261 #endif
0262 }
0263
0264
0265
0266
0267
0268 template <typename Iterator, typename Subject, typename Context>
0269 constexpr void set_expectation_failure(
0270 Iterator const& where,
0271 Subject const& subject,
0272 Context const& context
0273 ) {
0274 #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0275 boost::ignore_unused(where, subject, context);
0276
0277 #else
0278 using T = expectation_failure_t<Context>;
0279 static_assert(
0280 !std::is_same_v<unused_type, T>,
0281 "Context type was not specified for x3::expectation_failure_tag. "
0282 "You probably forgot: `x3::with<x3::expectation_failure_tag>(failure)[p]`. "
0283 "Note that you must also bind the context to your skipper."
0284 );
0285
0286 if constexpr (std::is_same_v<T, bool>)
0287 {
0288 boost::ignore_unused(where, subject);
0289 detail::set_expectation_failure_impl(
0290 x3::get<expectation_failure_tag>(context),
0291 true);
0292 }
0293 else
0294 {
0295 detail::set_expectation_failure_impl(
0296 x3::get<expectation_failure_tag>(context),
0297 expectation_failure<Iterator>(where, what(subject)));
0298 }
0299 #endif
0300 }
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323 template <typename AnyExpectationFailure, typename Context>
0324 constexpr void set_expectation_failure(
0325 AnyExpectationFailure const& existing_failure,
0326 Context const& context
0327 ) {
0328 #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0329 boost::ignore_unused(existing_failure, context);
0330
0331 #else
0332 using T = expectation_failure_t<Context>;
0333 static_assert(
0334 !std::is_same_v<T, unused_type>,
0335 "Context type was not specified for x3::expectation_failure_tag. "
0336 "You probably forgot: `x3::with<x3::expectation_failure_tag>(failure)[p]`. "
0337 "Note that you must also bind the context to your skipper."
0338 );
0339
0340 static_assert(
0341 std::is_assignable_v<T, AnyExpectationFailure const&>,
0342 "previous/current expectation failure types should be compatible"
0343 );
0344
0345 detail::set_expectation_failure_impl(
0346 x3::get<expectation_failure_tag>(context), existing_failure);
0347 #endif
0348 }
0349
0350 #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0351 template <typename Context>
0352 constexpr decltype(auto) get_expectation_failure(Context const&) = delete;
0353
0354 #else
0355 template <typename Context>
0356 BOOST_ATTRIBUTE_NODISCARD
0357 constexpr decltype(auto) get_expectation_failure(Context const& context)
0358 {
0359 using T = expectation_failure_t<Context>;
0360 static_assert(
0361 !std::is_same_v<T, unused_type>,
0362 "Context type was not specified for x3::expectation_failure_tag. "
0363 "You probably forgot: `x3::with<x3::expectation_failure_tag>(failure)[p]`. "
0364 "Note that you must also bind the context to your skipper."
0365 );
0366
0367 return x3::get<expectation_failure_tag>(context);
0368 }
0369 #endif
0370
0371 template <typename Context>
0372 constexpr void clear_expectation_failure(Context const& context) noexcept
0373 {
0374 #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0375 boost::ignore_unused(context);
0376 #else
0377 using T = expectation_failure_t<Context>;
0378 static_assert(
0379 !std::is_same_v<T, unused_type>,
0380 "Context type was not specified for x3::expectation_failure_tag. "
0381 "You probably forgot: `x3::with<x3::expectation_failure_tag>(failure)[p]`. "
0382 "Note that you must also bind the context to your skipper."
0383 );
0384 detail::clear_expectation_failure_impl(
0385 x3::get<expectation_failure_tag>(context));
0386 #endif
0387 }
0388
0389 }
0390 }}}
0391
0392 #endif