1 /*=============================================================================
2 Copyright (c) 2001-2003 Joel de Guzman
3 http://spirit.sourceforge.net/
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
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>
18 #include <boost/spirit/home/classic/error_handling/exceptions_fwd.hpp>
20 namespace boost { namespace spirit {
22 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
24 ///////////////////////////////////////////////////////////////////////////
26 // parser_error_base class
28 // This is the base class of parser_error (see below). This may be
29 // used to catch any type of parser error.
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.
36 ///////////////////////////////////////////////////////////////////////////
37 class parser_error_base : public std::exception
41 parser_error_base() {}
42 virtual ~parser_error_base() throw() {}
46 parser_error_base(parser_error_base const& rhs)
47 : std::exception(rhs) {}
48 parser_error_base& operator=(parser_error_base const&)
54 ///////////////////////////////////////////////////////////////////////////
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".
64 // The throw_ function creates and throws a parser_error given
65 // an iterator and an error descriptor.
67 ///////////////////////////////////////////////////////////////////////////
68 template <typename ErrorDescrT, typename IteratorT>
69 struct parser_error : public parser_error_base
71 typedef ErrorDescrT error_descr_t;
72 typedef IteratorT iterator_t;
74 parser_error(IteratorT where_, ErrorDescrT descriptor_)
75 : where(where_), descriptor(descriptor_) {}
77 parser_error(parser_error const& rhs)
78 : parser_error_base(rhs)
79 , where(rhs.where), descriptor(rhs.descriptor) {}
82 operator=(parser_error const& rhs)
85 descriptor = rhs.descriptor;
90 ~parser_error() throw() {}
95 return "BOOST_SPIRIT_CLASSIC_NS::parser_error";
99 ErrorDescrT descriptor;
102 //////////////////////////////////
103 template <typename ErrorDescrT, typename IteratorT>
105 throw_(IteratorT where, ErrorDescrT descriptor)
107 boost::throw_exception(
108 parser_error<ErrorDescrT, IteratorT>(where, descriptor));
111 ///////////////////////////////////////////////////////////////////////////
113 // assertive_parser class
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.
120 ///////////////////////////////////////////////////////////////////////////
121 template <typename ErrorDescrT, typename ParserT>
122 struct assertive_parser
123 : public unary<ParserT, parser<assertive_parser<ErrorDescrT, ParserT> > >
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;
129 assertive_parser(ParserT const& parser, ErrorDescrT descriptor_)
130 : base_t(parser), descriptor(descriptor_) {}
132 template <typename ScannerT>
135 typedef typename parser_result<ParserT, ScannerT>::type type;
138 template <typename ScannerT>
139 typename parser_result<self_t, ScannerT>::type
140 parse(ScannerT const& scan) const
142 typedef typename parser_result<ParserT, ScannerT>::type result_t;
144 result_t hit = this->subject().parse(scan);
147 throw_(scan.first, descriptor);
152 ErrorDescrT descriptor;
155 ///////////////////////////////////////////////////////////////////////////
159 // assertive_parsers are never instantiated directly. The assertion
160 // class is used to indirectly create an assertive_parser object.
161 // Before declaring the grammar, we declare some assertion objects.
166 // program_expected, begin_expected, end_expected
169 // assertion<Errors> expect_program(program_expected);
170 // assertion<Errors> expect_begin(begin_expected);
171 // assertion<Errors> expect_end(end_expected);
173 // Now, we can use these assertions as wrappers around parsers:
175 // expect_end(str_p("end"))
177 // Take note that although the example uses enums to hold the
178 // information regarding the error (error desccriptor), we are free
179 // to use other types such as integers and strings. Enums are
180 // convenient for error handlers to easily catch since C++ treats
181 // enums as unique types.
183 ///////////////////////////////////////////////////////////////////////////
184 template <typename ErrorDescrT>
187 assertion(ErrorDescrT descriptor_)
188 : descriptor(descriptor_) {}
190 template <typename ParserT>
191 assertive_parser<ErrorDescrT, ParserT>
192 operator()(ParserT const& parser) const
194 return assertive_parser<ErrorDescrT, ParserT>(parser, descriptor);
197 ErrorDescrT descriptor;
200 ///////////////////////////////////////////////////////////////////////////
204 // Where T is an attribute type compatible with the match attribute
205 // of the fallback_parser's subject (defaults to nil_t). The class
206 // error_status reports the result of an error handler (see
207 // fallback_parser). result can be one of:
209 // fail: quit and fail (return a no_match)
210 // retry: attempt error recovery, possibly moving the scanner
211 // accept: force success returning a matching length, moving
212 // the scanner appropriately and returning an attribute
214 // rethrow: rethrows the error.
216 ///////////////////////////////////////////////////////////////////////////
217 template <typename T>
220 enum result_t { fail, retry, accept, rethrow };
223 result_t result_ = fail,
224 std::ptrdiff_t length_ = -1,
225 T const& value_ = T())
226 : result(result_), length(length_), value(value_) {}
229 std::ptrdiff_t length;
233 ///////////////////////////////////////////////////////////////////////////
235 // fallback_parser class
237 // Handles exceptions of type parser_error<ErrorDescrT, IteratorT>
238 // thrown somewhere inside its embedded ParserT object. The class
239 // sets up a try block before delegating parsing to its subject.
240 // When an exception is caught, the catch block then calls the
241 // HandlerT object. HandlerT may be a function or a functor (with
242 // an operator() member function) compatible with the interface:
245 // handler(ScannerT const& scan, ErrorT error);
247 // Where scan points to the scanner state prior to parsing and error
248 // is the error that arose (see parser_error). The handler must
249 // return an error_status<T> object (see above).
251 ///////////////////////////////////////////////////////////////////////////
254 template <typename RT, typename ParserT, typename ScannerT>
255 RT fallback_parser_parse(ParserT const& p, ScannerT const& scan);
258 template <typename ErrorDescrT, typename ParserT, typename HandlerT>
259 struct fallback_parser
260 : public unary<ParserT,
261 parser<fallback_parser<ErrorDescrT, ParserT, HandlerT> > >
263 typedef fallback_parser<ErrorDescrT, ParserT, HandlerT>
267 typedef unary<ParserT, parser<self_t> >
269 typedef unary_parser_category
272 fallback_parser(ParserT const& parser, HandlerT const& handler_)
273 : base_t(parser), handler(handler_) {}
275 template <typename ScannerT>
278 typedef typename parser_result<ParserT, ScannerT>::type type;
281 template <typename ScannerT>
282 typename parser_result<self_t, ScannerT>::type
283 parse(ScannerT const& scan) const
285 typedef typename parser_result<self_t, ScannerT>::type result_t;
286 return impl::fallback_parser_parse<result_t>(*this, scan);
292 ///////////////////////////////////////////////////////////////////////////
296 // fallback_parser objects are not instantiated directly. The guard
297 // class is used to indirectly create a fallback_parser object.
298 // guards are typically predeclared just like assertions (see the
299 // assertion class above; the example extends the previous example
300 // introduced in the assertion class above):
302 // guard<Errors> my_guard;
304 // Errors, in this example is the error descriptor type we want to
305 // detect; This is essentially the ErrorDescrT template parameter
306 // of the fallback_parser class.
308 // my_guard may now be used in a grammar declaration as:
312 // where p is a parser, h is a function or functor compatible with
313 // fallback_parser's HandlerT (see above).
315 ///////////////////////////////////////////////////////////////////////////
316 template <typename ErrorDescrT, typename ParserT>
317 struct guard_gen : public unary<ParserT, nil_t>
319 typedef guard<ErrorDescrT> parser_generator_t;
320 typedef unary_parser_category parser_category_t;
322 guard_gen(ParserT const& p)
323 : unary<ParserT, nil_t>(p) {}
325 template <typename HandlerT>
326 fallback_parser<ErrorDescrT, ParserT, HandlerT>
327 operator[](HandlerT const& handler) const
329 return fallback_parser<ErrorDescrT, ParserT, HandlerT>
330 (this->subject(), handler);
334 template <typename ErrorDescrT>
337 template <typename ParserT>
340 typedef guard_gen<ErrorDescrT, ParserT> type;
343 template <typename ParserT>
344 static guard_gen<ErrorDescrT, ParserT>
345 generate(ParserT const& parser)
347 return guard_gen<ErrorDescrT, ParserT>(parser);
350 template <typename ParserT>
351 guard_gen<ErrorDescrT, ParserT>
352 operator()(ParserT const& parser) const
354 return guard_gen<ErrorDescrT, ParserT>(parser);
358 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
360 }} // namespace BOOST_SPIRIT_CLASSIC_NS
362 #include <boost/spirit/home/classic/error_handling/impl/exceptions.ipp>