File indexing completed on 2025-01-19 09:47:45
0001
0002
0003
0004
0005
0006
0007 #if !defined(BOOST_SPIRIT_ERROR_HANDLER_APRIL_29_2007_1042PM)
0008 #define BOOST_SPIRIT_ERROR_HANDLER_APRIL_29_2007_1042PM
0009
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013
0014 #include <boost/spirit/home/qi/operator/expect.hpp>
0015 #include <boost/spirit/home/qi/nonterminal/rule.hpp>
0016 #include <boost/spirit/home/support/multi_pass_wrapper.hpp>
0017 #include <boost/function.hpp>
0018 #include <boost/assert.hpp>
0019
0020 namespace boost { namespace spirit { namespace qi
0021 {
0022 enum error_handler_result
0023 {
0024 fail
0025 , retry
0026 , accept
0027 , rethrow
0028 };
0029
0030 namespace detail
0031 {
0032
0033
0034
0035 template <typename Iterator, bool active>
0036 struct reset_on_exit
0037 {
0038 reset_on_exit(Iterator&) {}
0039 };
0040
0041
0042
0043
0044
0045 template <typename Iterator>
0046 struct reset_on_exit<Iterator, true>
0047 {
0048 reset_on_exit(Iterator& it)
0049 : it_(it)
0050 , inhibit_clear_queue_(spirit::traits::inhibit_clear_queue(it))
0051 {
0052 spirit::traits::inhibit_clear_queue(it_, true);
0053 }
0054
0055 ~reset_on_exit()
0056 {
0057
0058 spirit::traits::inhibit_clear_queue(it_, inhibit_clear_queue_);
0059 }
0060
0061 Iterator& it_;
0062 bool inhibit_clear_queue_;
0063 };
0064 }
0065
0066 template <
0067 typename Iterator, typename Context
0068 , typename Skipper, typename F, error_handler_result action
0069 >
0070 struct error_handler
0071 {
0072 typedef function<
0073 bool(Iterator& first, Iterator const& last
0074 , Context& context
0075 , Skipper const& skipper
0076 )>
0077 function_type;
0078
0079 error_handler(function_type subject_, F f_)
0080 : subject(subject_)
0081 , f(f_)
0082 {
0083 }
0084
0085 bool operator()(
0086 Iterator& first, Iterator const& last
0087 , Context& context, Skipper const& skipper) const
0088 {
0089 typedef qi::detail::reset_on_exit<Iterator
0090 , traits::is_multi_pass<Iterator>::value &&
0091 (action == retry || action == fail)> on_exit_type;
0092
0093 on_exit_type on_exit(first);
0094 for(;;)
0095 {
0096 try
0097 {
0098 Iterator i = first;
0099 bool r = subject(i, last, context, skipper);
0100 if (r)
0101 first = i;
0102 return r;
0103 }
0104 catch (expectation_failure<Iterator> const& x)
0105 {
0106 typedef
0107 fusion::vector<
0108 Iterator&
0109 , Iterator const&
0110 , Iterator const&
0111 , info const&>
0112 params;
0113 error_handler_result r = action;
0114 params args(first, last, x.first, x.what_);
0115 f(args, context, r);
0116
0117
0118
0119
0120
0121
0122
0123 switch (r)
0124 {
0125 case fail:
0126 BOOST_ASSERT(
0127 !traits::is_multi_pass<Iterator>::value ||
0128 action == retry || action == fail);
0129 return false;
0130 case retry:
0131 BOOST_ASSERT(
0132 !traits::is_multi_pass<Iterator>::value ||
0133 action == retry || action == fail);
0134 continue;
0135 case accept: return true;
0136 case rethrow: boost::throw_exception(x);
0137 }
0138 }
0139 }
0140 return false;
0141 }
0142
0143 function_type subject;
0144 F f;
0145 };
0146
0147 template <
0148 error_handler_result action
0149 , typename Iterator, typename T0, typename T1, typename T2
0150 , typename F>
0151 void on_error(rule<Iterator, T0, T1, T2>& r, F f)
0152 {
0153 typedef rule<Iterator, T0, T1, T2> rule_type;
0154
0155 typedef
0156 error_handler<
0157 Iterator
0158 , typename rule_type::context_type
0159 , typename rule_type::skipper_type
0160 , F
0161 , action>
0162 error_handler;
0163 r.f = error_handler(r.f, f);
0164 }
0165
0166
0167
0168 template <typename Iterator, typename T0, typename T1
0169 , typename T2, typename F>
0170 void on_error(rule<Iterator, T0, T1, T2>& r, F f)
0171 {
0172 on_error<fail>(r, f);
0173 }
0174 }}}
0175
0176 #endif