source: NonGTP/Boost/boost/spirit/error_handling/exceptions.hpp @ 857

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