]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/include/boost/spirit/home/qi/nonterminal/error_handler.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / qi / nonterminal / error_handler.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6==============================================================================*/
7#if !defined(BOOST_SPIRIT_ERROR_HANDLER_APRIL_29_2007_1042PM)
8#define BOOST_SPIRIT_ERROR_HANDLER_APRIL_29_2007_1042PM
9
10#if defined(_MSC_VER)
11#pragma once
12#endif
13
14#include <boost/spirit/home/qi/operator/expect.hpp>
15#include <boost/spirit/home/qi/nonterminal/rule.hpp>
16#include <boost/spirit/home/support/multi_pass_wrapper.hpp>
17#include <boost/function.hpp>
18#include <boost/assert.hpp>
19
20namespace boost { namespace spirit { namespace qi
21{
22 enum error_handler_result
23 {
24 fail
25 , retry
26 , accept
27 , rethrow
28 };
29
30 namespace detail
31 {
32 // Helper template allowing to manage the inhibit clear queue flag in
33 // a multi_pass iterator. This is the usual specialization used for
34 // anything but a multi_pass iterator.
35 template <typename Iterator, bool active>
36 struct reset_on_exit
37 {
38 reset_on_exit(Iterator&) {}
39 };
40
41 // For 'retry' or 'fail' error handlers we need to inhibit the flushing
42 // of the internal multi_pass buffers which otherwise might happen at
43 // deterministic expectation points inside the encapsulated right hand
44 // side of rule.
45 template <typename Iterator>
46 struct reset_on_exit<Iterator, true>
47 {
48 reset_on_exit(Iterator& it)
49 : it_(it)
50 , inhibit_clear_queue_(spirit::traits::inhibit_clear_queue(it))
51 {
52 spirit::traits::inhibit_clear_queue(it_, true);
53 }
54
55 ~reset_on_exit()
56 {
57 // reset inhibit flag in multi_pass on exit
58 spirit::traits::inhibit_clear_queue(it_, inhibit_clear_queue_);
59 }
60
61 Iterator& it_;
62 bool inhibit_clear_queue_;
63 };
64 }
65
66 template <
67 typename Iterator, typename Context
68 , typename Skipper, typename F, error_handler_result action
69 >
70 struct error_handler
71 {
72 typedef function<
73 bool(Iterator& first, Iterator const& last
74 , Context& context
75 , Skipper const& skipper
76 )>
77 function_type;
78
79 error_handler(function_type subject_, F f_)
80 : subject(subject_)
81 , f(f_)
82 {
83 }
84
85 bool operator()(
86 Iterator& first, Iterator const& last
87 , Context& context, Skipper const& skipper) const
88 {
89 typedef qi::detail::reset_on_exit<Iterator
90 , traits::is_multi_pass<Iterator>::value &&
91 (action == retry || action == fail)> on_exit_type;
92
93 on_exit_type on_exit(first);
94 for(;;)
95 {
96 try
97 {
98 Iterator i = first;
99 bool r = subject(i, last, context, skipper);
100 if (r)
101 first = i;
102 return r;
103 }
104 catch (expectation_failure<Iterator> const& x)
105 {
106 typedef
107 fusion::vector<
108 Iterator&
109 , Iterator const&
110 , Iterator const&
111 , info const&>
112 params;
113 error_handler_result r = action;
114 params args(first, last, x.first, x.what_);
115 f(args, context, r);
116
117 // The assertions below will fire if you are using a
118 // multi_pass as the underlying iterator, one of your error
119 // handlers forced its guarded rule to 'fail' or 'retry',
120 // and the error handler has not been instantiated using
121 // either 'fail' or 'retry' in the first place. Please see
122 // the multi_pass docs for more information.
123 switch (r)
124 {
125 case fail:
126 BOOST_ASSERT(
127 !traits::is_multi_pass<Iterator>::value ||
128 action == retry || action == fail);
129 return false;
130 case retry:
131 BOOST_ASSERT(
132 !traits::is_multi_pass<Iterator>::value ||
133 action == retry || action == fail);
134 continue;
135 case accept: return true;
136 case rethrow: boost::throw_exception(x);
137 }
138 }
139 }
140 return false;
141 }
142
143 function_type subject;
144 F f;
145 };
146
147 template <
148 error_handler_result action
149 , typename Iterator, typename T0, typename T1, typename T2
150 , typename F>
151 void on_error(rule<Iterator, T0, T1, T2>& r, F f)
152 {
153 typedef rule<Iterator, T0, T1, T2> rule_type;
154
155 typedef
156 error_handler<
157 Iterator
158 , typename rule_type::context_type
159 , typename rule_type::skipper_type
160 , F
161 , action>
162 error_handler;
163 r.f = error_handler(r.f, f);
164 }
165
166 // Error handling support when <action> is not
167 // specified. We will default to <fail>.
168 template <typename Iterator, typename T0, typename T1
169 , typename T2, typename F>
170 void on_error(rule<Iterator, T0, T1, T2>& r, F f)
171 {
172 on_error<fail>(r, f);
173 }
174}}}
175
176#endif