]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/classic/error_handling/exceptions.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / classic / error_handling / exceptions.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2003 Joel de Guzman
3 http://spirit.sourceforge.net/
4
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 #ifndef BOOST_SPIRIT_EXCEPTIONS_HPP
9 #define BOOST_SPIRIT_EXCEPTIONS_HPP
10
11 #include <boost/config.hpp>
12 #include <boost/throw_exception.hpp>
13 #include <boost/spirit/home/classic/namespace.hpp>
14 #include <boost/spirit/home/classic/core/parser.hpp>
15 #include <boost/spirit/home/classic/core/composite/composite.hpp>
16 #include <exception>
17
18 #include <boost/spirit/home/classic/error_handling/exceptions_fwd.hpp>
19
20 namespace boost { namespace spirit {
21
22 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
23
24 ///////////////////////////////////////////////////////////////////////////
25 //
26 // parser_error_base class
27 //
28 // This is the base class of parser_error (see below). This may be
29 // used to catch any type of parser error.
30 //
31 // This exception shouldn't propagate outside the parser. However to
32 // avoid quirks of many platforms/implementations which fall outside
33 // the C++ standard, we derive parser_error_base from std::exception
34 // to allow a single catch handler to catch all exceptions.
35 //
36 ///////////////////////////////////////////////////////////////////////////
37 class parser_error_base : public std::exception
38 {
39 protected:
40
41 parser_error_base() {}
42 virtual ~parser_error_base() throw() {}
43
44 public:
45
46 parser_error_base(parser_error_base const& rhs)
47 : std::exception(rhs) {}
48 parser_error_base& operator=(parser_error_base const&)
49 {
50 return *this;
51 }
52 };
53
54 ///////////////////////////////////////////////////////////////////////////
55 //
56 // parser_error class
57 //
58 // Generic parser exception class. This is the base class for all
59 // parser exceptions. The exception holds the iterator position
60 // where the error was encountered in its member variable "where".
61 // The parser_error also holds information regarding the error
62 // (error descriptor) in its member variable "descriptor".
63 //
64 // The throw_ function creates and throws a parser_error given
65 // an iterator and an error descriptor.
66 //
67 ///////////////////////////////////////////////////////////////////////////
68 template <typename ErrorDescrT, typename IteratorT>
69 struct parser_error : public parser_error_base
70 {
71 typedef ErrorDescrT error_descr_t;
72 typedef IteratorT iterator_t;
73
74 parser_error(IteratorT where_, ErrorDescrT descriptor_)
75 : where(where_), descriptor(descriptor_) {}
76
77 parser_error(parser_error const& rhs)
78 : parser_error_base(rhs)
79 , where(rhs.where), descriptor(rhs.descriptor) {}
80
81 parser_error&
82 operator=(parser_error const& rhs)
83 {
84 where = rhs.where;
85 descriptor = rhs.descriptor;
86 return *this;
87 }
88
89 virtual
90 ~parser_error() throw() {}
91
92 virtual const char*
93 what() const throw()
94 {
95 return "BOOST_SPIRIT_CLASSIC_NS::parser_error";
96 }
97
98 IteratorT where;
99 ErrorDescrT descriptor;
100 };
101
102 //////////////////////////////////
103 template <typename ErrorDescrT, typename IteratorT>
104 inline void
105 throw_(IteratorT where, ErrorDescrT descriptor)
106 {
107 boost::throw_exception(
108 parser_error<ErrorDescrT, IteratorT>(where, descriptor));
109 }
110
111 ///////////////////////////////////////////////////////////////////////////
112 //
113 // assertive_parser class
114 //
115 // An assertive_parser class is a parser that throws an exception
116 // in response to a parsing failure. The assertive_parser throws a
117 // parser_error exception rather than returning an unsuccessful
118 // match to signal that the parser failed to match the input.
119 //
120 ///////////////////////////////////////////////////////////////////////////
121 template <typename ErrorDescrT, typename ParserT>
122 struct assertive_parser
123 : public unary<ParserT, parser<assertive_parser<ErrorDescrT, ParserT> > >
124 {
125 typedef assertive_parser<ErrorDescrT, ParserT> self_t;
126 typedef unary<ParserT, parser<self_t> > base_t;
127 typedef unary_parser_category parser_category_t;
128
129 assertive_parser(ParserT const& parser, ErrorDescrT descriptor_)
130 : base_t(parser), descriptor(descriptor_) {}
131
132 template <typename ScannerT>
133 struct result
134 {
135 typedef typename parser_result<ParserT, ScannerT>::type type;
136 };
137
138 template <typename ScannerT>
139 typename parser_result<self_t, ScannerT>::type
140 parse(ScannerT const& scan) const
141 {
142 typedef typename parser_result<ParserT, ScannerT>::type result_t;
143 typedef typename ScannerT::iterator_t iterator_t;
144
145 result_t hit = this->subject().parse(scan);
146 if (!hit)
147 {
148 throw_(scan.first, descriptor);
149 }
150 return hit;
151 }
152
153 ErrorDescrT descriptor;
154 };
155
156 ///////////////////////////////////////////////////////////////////////////
157 //
158 // assertion class
159 //
160 // assertive_parsers are never instantiated directly. The assertion
161 // class is used to indirectly create an assertive_parser object.
162 // Before declaring the grammar, we declare some assertion objects.
163 // Examples:
164 //
165 // enum Errors
166 // {
167 // program_expected, begin_expected, end_expected
168 // };
169 //
170 // assertion<Errors> expect_program(program_expected);
171 // assertion<Errors> expect_begin(begin_expected);
172 // assertion<Errors> expect_end(end_expected);
173 //
174 // Now, we can use these assertions as wrappers around parsers:
175 //
176 // expect_end(str_p("end"))
177 //
178 // Take note that although the example uses enums to hold the
179 // information regarding the error (error desccriptor), we are free
180 // to use other types such as integers and strings. Enums are
181 // convenient for error handlers to easily catch since C++ treats
182 // enums as unique types.
183 //
184 ///////////////////////////////////////////////////////////////////////////
185 template <typename ErrorDescrT>
186 struct assertion
187 {
188 assertion(ErrorDescrT descriptor_)
189 : descriptor(descriptor_) {}
190
191 template <typename ParserT>
192 assertive_parser<ErrorDescrT, ParserT>
193 operator()(ParserT const& parser) const
194 {
195 return assertive_parser<ErrorDescrT, ParserT>(parser, descriptor);
196 }
197
198 ErrorDescrT descriptor;
199 };
200
201 ///////////////////////////////////////////////////////////////////////////
202 //
203 // error_status<T>
204 //
205 // Where T is an attribute type compatible with the match attribute
206 // of the fallback_parser's subject (defaults to nil_t). The class
207 // error_status reports the result of an error handler (see
208 // fallback_parser). result can be one of:
209 //
210 // fail: quit and fail (return a no_match)
211 // retry: attempt error recovery, possibly moving the scanner
212 // accept: force success returning a matching length, moving
213 // the scanner appropriately and returning an attribute
214 // value
215 // rethrow: rethrows the error.
216 //
217 ///////////////////////////////////////////////////////////////////////////
218 template <typename T>
219 struct error_status
220 {
221 enum result_t { fail, retry, accept, rethrow };
222
223 error_status(
224 result_t result_ = fail,
225 std::ptrdiff_t length_ = -1,
226 T const& value_ = T())
227 : result(result_), length(length_), value(value_) {}
228
229 result_t result;
230 std::ptrdiff_t length;
231 T value;
232 };
233
234 ///////////////////////////////////////////////////////////////////////////
235 //
236 // fallback_parser class
237 //
238 // Handles exceptions of type parser_error<ErrorDescrT, IteratorT>
239 // thrown somewhere inside its embedded ParserT object. The class
240 // sets up a try block before delegating parsing to its subject.
241 // When an exception is caught, the catch block then calls the
242 // HandlerT object. HandlerT may be a function or a functor (with
243 // an operator() member function) compatible with the interface:
244 //
245 // error_status<T>
246 // handler(ScannerT const& scan, ErrorT error);
247 //
248 // Where scan points to the scanner state prior to parsing and error
249 // is the error that arose (see parser_error). The handler must
250 // return an error_status<T> object (see above).
251 //
252 ///////////////////////////////////////////////////////////////////////////
253 namespace impl
254 {
255 template <typename RT, typename ParserT, typename ScannerT>
256 RT fallback_parser_parse(ParserT const& p, ScannerT const& scan);
257 }
258
259 template <typename ErrorDescrT, typename ParserT, typename HandlerT>
260 struct fallback_parser
261 : public unary<ParserT,
262 parser<fallback_parser<ErrorDescrT, ParserT, HandlerT> > >
263 {
264 typedef fallback_parser<ErrorDescrT, ParserT, HandlerT>
265 self_t;
266 typedef ErrorDescrT
267 error_descr_t;
268 typedef unary<ParserT, parser<self_t> >
269 base_t;
270 typedef unary_parser_category
271 parser_category_t;
272
273 fallback_parser(ParserT const& parser, HandlerT const& handler_)
274 : base_t(parser), handler(handler_) {}
275
276 template <typename ScannerT>
277 struct result
278 {
279 typedef typename parser_result<ParserT, ScannerT>::type type;
280 };
281
282 template <typename ScannerT>
283 typename parser_result<self_t, ScannerT>::type
284 parse(ScannerT const& scan) const
285 {
286 typedef typename parser_result<self_t, ScannerT>::type result_t;
287 return impl::fallback_parser_parse<result_t>(*this, scan);
288 }
289
290 HandlerT handler;
291 };
292
293 ///////////////////////////////////////////////////////////////////////////
294 //
295 // guard class
296 //
297 // fallback_parser objects are not instantiated directly. The guard
298 // class is used to indirectly create a fallback_parser object.
299 // guards are typically predeclared just like assertions (see the
300 // assertion class above; the example extends the previous example
301 // introduced in the assertion class above):
302 //
303 // guard<Errors> my_guard;
304 //
305 // Errors, in this example is the error descriptor type we want to
306 // detect; This is essentially the ErrorDescrT template parameter
307 // of the fallback_parser class.
308 //
309 // my_guard may now be used in a grammar declaration as:
310 //
311 // my_guard(p)[h]
312 //
313 // where p is a parser, h is a function or functor compatible with
314 // fallback_parser's HandlerT (see above).
315 //
316 ///////////////////////////////////////////////////////////////////////////
317 template <typename ErrorDescrT, typename ParserT>
318 struct guard_gen : public unary<ParserT, nil_t>
319 {
320 typedef guard<ErrorDescrT> parser_generator_t;
321 typedef unary_parser_category parser_category_t;
322
323 guard_gen(ParserT const& p)
324 : unary<ParserT, nil_t>(p) {}
325
326 template <typename HandlerT>
327 fallback_parser<ErrorDescrT, ParserT, HandlerT>
328 operator[](HandlerT const& handler) const
329 {
330 return fallback_parser<ErrorDescrT, ParserT, HandlerT>
331 (this->subject(), handler);
332 }
333 };
334
335 template <typename ErrorDescrT>
336 struct guard
337 {
338 template <typename ParserT>
339 struct result
340 {
341 typedef guard_gen<ErrorDescrT, ParserT> type;
342 };
343
344 template <typename ParserT>
345 static guard_gen<ErrorDescrT, ParserT>
346 generate(ParserT const& parser)
347 {
348 return guard_gen<ErrorDescrT, ParserT>(parser);
349 }
350
351 template <typename ParserT>
352 guard_gen<ErrorDescrT, ParserT>
353 operator()(ParserT const& parser) const
354 {
355 return guard_gen<ErrorDescrT, ParserT>(parser);
356 }
357 };
358
359 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
360
361 }} // namespace BOOST_SPIRIT_CLASSIC_NS
362
363 #include <boost/spirit/home/classic/error_handling/impl/exceptions.ipp>
364 #endif
365