guard.hpp 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Copyright (c) 2017 wanghan02
  4. Copyright (c) 2024 Nana Sakisaka
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #if !defined(BOOST_SPIRIT_X3_GUARD_FERBRUARY_02_2013_0649PM)
  9. #define BOOST_SPIRIT_X3_GUARD_FERBRUARY_02_2013_0649PM
  10. #include <boost/spirit/home/x3/support/context.hpp>
  11. #include <boost/spirit/home/x3/support/expectation.hpp>
  12. #include <boost/spirit/home/x3/core/parser.hpp>
  13. namespace boost { namespace spirit { namespace x3
  14. {
  15. enum class error_handler_result
  16. {
  17. fail
  18. , retry
  19. , accept
  20. , rethrow // see BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE for alternative behaviors
  21. };
  22. template <typename Subject, typename Handler>
  23. struct guard : unary_parser<Subject, guard<Subject, Handler>>
  24. {
  25. typedef unary_parser<Subject, guard<Subject, Handler>> base_type;
  26. static bool const is_pass_through_unary = true;
  27. constexpr guard(Subject const& subject, Handler handler)
  28. : base_type(subject), handler(handler) {}
  29. template <typename Iterator, typename Context
  30. , typename RuleContext, typename Attribute>
  31. bool parse(Iterator& first, Iterator const& last
  32. , Context const& context, RuleContext& rcontext, Attribute& attr) const
  33. {
  34. for (;;)
  35. {
  36. Iterator i = first;
  37. #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
  38. try
  39. #endif
  40. {
  41. if (this->subject.parse(i, last, context, rcontext, attr))
  42. {
  43. first = i;
  44. return true;
  45. }
  46. }
  47. #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
  48. catch (expectation_failure<Iterator> const& x) {
  49. #else
  50. if (has_expectation_failure(context)) {
  51. auto& x = get_expectation_failure(context);
  52. #endif
  53. // X3 developer note: don't forget to sync this implementation with x3::detail::rule_parser
  54. switch (handler(first, last, x, context))
  55. {
  56. case error_handler_result::fail:
  57. clear_expectation_failure(context);
  58. return false;
  59. case error_handler_result::retry:
  60. continue;
  61. case error_handler_result::accept:
  62. return true;
  63. case error_handler_result::rethrow:
  64. #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
  65. throw;
  66. #else
  67. return false; // TODO: design decision required
  68. #endif
  69. }
  70. }
  71. return false;
  72. }
  73. }
  74. Handler handler;
  75. };
  76. }}}
  77. #endif