PageRenderTime 35ms CodeModel.GetById 17ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/classic/error_handling/exceptions.hpp

http://hadesmem.googlecode.com/
C++ Header | 365 lines | 187 code | 44 blank | 134 comment | 1 complexity | 261113c6002ce566b9b756fc9debe591 MD5 | raw file
  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
 20namespace boost { namespace spirit {
 21
 22BOOST_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
359BOOST_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