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;
143 typedef typename ScannerT::iterator_t iterator_t;
145 result_t hit = this->subject().parse(scan);
148 throw_(scan.first, descriptor);
153 ErrorDescrT descriptor;
156 ///////////////////////////////////////////////////////////////////////////
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.
167 // program_expected, begin_expected, end_expected
170 // assertion<Errors> expect_program(program_expected);
171 // assertion<Errors> expect_begin(begin_expected);
172 // assertion<Errors> expect_end(end_expected);
174 // Now, we can use these assertions as wrappers around parsers:
176 // expect_end(str_p("end"))
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.
184 ///////////////////////////////////////////////////////////////////////////
185 template <typename ErrorDescrT>
188 assertion(ErrorDescrT descriptor_)
189 : descriptor(descriptor_) {}
191 template <typename ParserT>
192 assertive_parser<ErrorDescrT, ParserT>
193 operator()(ParserT const& parser) const
195 return assertive_parser<ErrorDescrT, ParserT>(parser, descriptor);
198 ErrorDescrT descriptor;
201 ///////////////////////////////////////////////////////////////////////////
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:
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
215 // rethrow: rethrows the error.
217 ///////////////////////////////////////////////////////////////////////////
218 template <typename T>
221 enum result_t { fail, retry, accept, rethrow };
224 result_t result_ = fail,
225 std::ptrdiff_t length_ = -1,
226 T const& value_ = T())
227 : result(result_), length(length_), value(value_) {}
230 std::ptrdiff_t length;
234 ///////////////////////////////////////////////////////////////////////////
236 // fallback_parser class
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:
246 // handler(ScannerT const& scan, ErrorT error);
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).
252 ///////////////////////////////////////////////////////////////////////////
255 template <typename RT, typename ParserT, typename ScannerT>
256 RT fallback_parser_parse(ParserT const& p, ScannerT const& scan);
259 template <typename ErrorDescrT, typename ParserT, typename HandlerT>
260 struct fallback_parser
261 : public unary<ParserT,
262 parser<fallback_parser<ErrorDescrT, ParserT, HandlerT> > >
264 typedef fallback_parser<ErrorDescrT, ParserT, HandlerT>
268 typedef unary<ParserT, parser<self_t> >
270 typedef unary_parser_category
273 fallback_parser(ParserT const& parser, HandlerT const& handler_)
274 : base_t(parser), handler(handler_) {}
276 template <typename ScannerT>
279 typedef typename parser_result<ParserT, ScannerT>::type type;
282 template <typename ScannerT>
283 typename parser_result<self_t, ScannerT>::type
284 parse(ScannerT const& scan) const
286 typedef typename parser_result<self_t, ScannerT>::type result_t;
287 return impl::fallback_parser_parse<result_t>(*this, scan);
293 ///////////////////////////////////////////////////////////////////////////
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):
303 // guard<Errors> my_guard;
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.
309 // my_guard may now be used in a grammar declaration as:
313 // where p is a parser, h is a function or functor compatible with
314 // fallback_parser's HandlerT (see above).
316 ///////////////////////////////////////////////////////////////////////////
317 template <typename ErrorDescrT, typename ParserT>
318 struct guard_gen : public unary<ParserT, nil_t>
320 typedef guard<ErrorDescrT> parser_generator_t;
321 typedef unary_parser_category parser_category_t;
323 guard_gen(ParserT const& p)
324 : unary<ParserT, nil_t>(p) {}
326 template <typename HandlerT>
327 fallback_parser<ErrorDescrT, ParserT, HandlerT>
328 operator[](HandlerT const& handler) const
330 return fallback_parser<ErrorDescrT, ParserT, HandlerT>
331 (this->subject(), handler);
335 template <typename ErrorDescrT>
338 template <typename ParserT>
341 typedef guard_gen<ErrorDescrT, ParserT> type;
344 template <typename ParserT>
345 static guard_gen<ErrorDescrT, ParserT>
346 generate(ParserT const& parser)
348 return guard_gen<ErrorDescrT, ParserT>(parser);
351 template <typename ParserT>
352 guard_gen<ErrorDescrT, ParserT>
353 operator()(ParserT const& parser) const
355 return guard_gen<ErrorDescrT, ParserT>(parser);
359 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
361 }} // namespace BOOST_SPIRIT_CLASSIC_NS
363 #include <boost/spirit/home/classic/error_handling/impl/exceptions.ipp>