Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:01:57

0001 /*=============================================================================
0002     Copyright (c) 2001-2003 Joel de Guzman
0003     http://spirit.sourceforge.net/
0004 
0005   Distributed under the Boost Software License, Version 1.0. (See accompanying
0006   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 =============================================================================*/
0008 #ifndef BOOST_SPIRIT_EXCEPTIONS_HPP
0009 #define BOOST_SPIRIT_EXCEPTIONS_HPP
0010 
0011 #include <boost/config.hpp>
0012 #include <boost/throw_exception.hpp>
0013 #include <boost/spirit/home/classic/namespace.hpp>
0014 #include <boost/spirit/home/classic/core/parser.hpp>
0015 #include <boost/spirit/home/classic/core/composite/composite.hpp>
0016 #include <exception>
0017 
0018 #include <boost/spirit/home/classic/error_handling/exceptions_fwd.hpp>
0019 
0020 namespace boost { namespace spirit {
0021 
0022 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0023 
0024     ///////////////////////////////////////////////////////////////////////////
0025     //
0026     //  parser_error_base class
0027     //
0028     //      This is the base class of parser_error (see below). This may be
0029     //      used to catch any type of parser error.
0030     //
0031     //      This exception shouldn't propagate outside the parser. However to
0032     //      avoid quirks of many platforms/implementations which fall outside
0033     //      the C++ standard, we derive parser_error_base from std::exception
0034     //      to allow a single catch handler to catch all exceptions.
0035     //
0036     ///////////////////////////////////////////////////////////////////////////
0037     class BOOST_SYMBOL_VISIBLE parser_error_base : public std::exception
0038     {
0039     protected:
0040 
0041         parser_error_base() {}
0042         virtual ~parser_error_base() BOOST_NOEXCEPT_OR_NOTHROW {}
0043 
0044     public:
0045 
0046         parser_error_base(parser_error_base const& rhs)
0047             : std::exception(rhs) {}
0048         parser_error_base& operator=(parser_error_base const&)
0049         {
0050             return *this;
0051         }
0052     };
0053 
0054     ///////////////////////////////////////////////////////////////////////////
0055     //
0056     //  parser_error class
0057     //
0058     //      Generic parser exception class. This is the base class for all
0059     //      parser exceptions. The exception holds the iterator position
0060     //      where the error was encountered in its member variable "where".
0061     //      The parser_error also holds information regarding the error
0062     //      (error descriptor) in its member variable "descriptor".
0063     //
0064     //      The throw_ function creates and throws a parser_error given
0065     //      an iterator and an error descriptor.
0066     //
0067     ///////////////////////////////////////////////////////////////////////////
0068     template <typename ErrorDescrT, typename IteratorT>
0069     struct parser_error : public parser_error_base
0070     {
0071         typedef ErrorDescrT error_descr_t;
0072         typedef IteratorT iterator_t;
0073 
0074         parser_error(IteratorT where_, ErrorDescrT descriptor_)
0075         : where(where_), descriptor(descriptor_) {}
0076 
0077         parser_error(parser_error const& rhs)
0078         : parser_error_base(rhs)
0079         , where(rhs.where), descriptor(rhs.descriptor) {}
0080 
0081         parser_error&
0082         operator=(parser_error const& rhs)
0083         {
0084             where = rhs.where;
0085             descriptor = rhs.descriptor;
0086             return *this;
0087         }
0088 
0089         virtual
0090         ~parser_error() BOOST_NOEXCEPT_OR_NOTHROW {}
0091 
0092         virtual const char*
0093         what() const BOOST_NOEXCEPT_OR_NOTHROW
0094         {
0095             return "BOOST_SPIRIT_CLASSIC_NS::parser_error";
0096         }
0097 
0098         IteratorT where;
0099         ErrorDescrT descriptor;
0100     };
0101 
0102     //////////////////////////////////
0103     template <typename ErrorDescrT, typename IteratorT>
0104     inline void
0105     throw_(IteratorT where, ErrorDescrT descriptor)
0106     {
0107          boost::throw_exception(
0108             parser_error<ErrorDescrT, IteratorT>(where, descriptor));
0109     }
0110 
0111     ///////////////////////////////////////////////////////////////////////////
0112     //
0113     //  assertive_parser class
0114     //
0115     //      An assertive_parser class is a parser that throws an exception
0116     //      in response to a parsing failure. The assertive_parser throws a
0117     //      parser_error exception rather than returning an unsuccessful
0118     //      match to signal that the parser failed to match the input.
0119     //
0120     ///////////////////////////////////////////////////////////////////////////
0121     template <typename ErrorDescrT, typename ParserT>
0122     struct assertive_parser
0123     :   public unary<ParserT, parser<assertive_parser<ErrorDescrT, ParserT> > >
0124     {
0125         typedef assertive_parser<ErrorDescrT, ParserT>  self_t;
0126         typedef unary<ParserT, parser<self_t> >         base_t;
0127         typedef unary_parser_category                   parser_category_t;
0128 
0129         assertive_parser(ParserT const& parser, ErrorDescrT descriptor_)
0130         : base_t(parser), descriptor(descriptor_) {}
0131 
0132         template <typename ScannerT>
0133         struct result
0134         {
0135             typedef typename parser_result<ParserT, ScannerT>::type type;
0136         };
0137 
0138         template <typename ScannerT>
0139         typename parser_result<self_t, ScannerT>::type
0140         parse(ScannerT const& scan) const
0141         {
0142             typedef typename parser_result<ParserT, ScannerT>::type result_t;
0143 
0144             result_t hit = this->subject().parse(scan);
0145             if (!hit)
0146             {
0147                 throw_(scan.first, descriptor);
0148             }
0149             return hit;
0150         }
0151 
0152         ErrorDescrT descriptor;
0153     };
0154 
0155     ///////////////////////////////////////////////////////////////////////////
0156     //
0157     //  assertion class
0158     //
0159     //      assertive_parsers are never instantiated directly. The assertion
0160     //      class is used to indirectly create an assertive_parser object.
0161     //      Before declaring the grammar, we declare some assertion objects.
0162     //      Examples:
0163     //
0164     //          enum Errors
0165     //          {
0166     //              program_expected, begin_expected, end_expected
0167     //          };
0168     //
0169     //          assertion<Errors>   expect_program(program_expected);
0170     //          assertion<Errors>   expect_begin(begin_expected);
0171     //          assertion<Errors>   expect_end(end_expected);
0172     //
0173     //      Now, we can use these assertions as wrappers around parsers:
0174     //
0175     //          expect_end(str_p("end"))
0176     //
0177     //      Take note that although the example uses enums to hold the
0178     //      information regarding the error (error desccriptor), we are free
0179     //      to use other types such as integers and strings. Enums are
0180     //      convenient for error handlers to easily catch since C++ treats
0181     //      enums as unique types.
0182     //
0183     ///////////////////////////////////////////////////////////////////////////
0184     template <typename ErrorDescrT>
0185     struct assertion
0186     {
0187         assertion(ErrorDescrT descriptor_)
0188         : descriptor(descriptor_) {}
0189 
0190         template <typename ParserT>
0191         assertive_parser<ErrorDescrT, ParserT>
0192         operator()(ParserT const& parser) const
0193         {
0194             return assertive_parser<ErrorDescrT, ParserT>(parser, descriptor);
0195         }
0196 
0197         ErrorDescrT descriptor;
0198     };
0199 
0200     ///////////////////////////////////////////////////////////////////////////
0201     //
0202     //  error_status<T>
0203     //
0204     //      Where T is an attribute type compatible with the match attribute
0205     //      of the fallback_parser's subject (defaults to nil_t). The class
0206     //      error_status reports the result of an error handler (see
0207     //      fallback_parser). result can be one of:
0208     //
0209     //          fail:       quit and fail (return a no_match)
0210     //          retry:      attempt error recovery, possibly moving the scanner
0211     //          accept:     force success returning a matching length, moving
0212     //                      the scanner appropriately and returning an attribute
0213     //                      value
0214     //          rethrow:    rethrows the error.
0215     //
0216     ///////////////////////////////////////////////////////////////////////////
0217     template <typename T>
0218     struct error_status
0219     {
0220         enum result_t { fail, retry, accept, rethrow };
0221 
0222         error_status(
0223             result_t result_ = fail,
0224             std::ptrdiff_t length_ = -1,
0225             T const& value_ = T())
0226         : result(result_), length(length_), value(value_) {}
0227 
0228         result_t        result;
0229         std::ptrdiff_t  length;
0230         T               value;
0231     };
0232 
0233     ///////////////////////////////////////////////////////////////////////////
0234     //
0235     //  fallback_parser class
0236     //
0237     //      Handles exceptions of type parser_error<ErrorDescrT, IteratorT>
0238     //      thrown somewhere inside its embedded ParserT object. The class
0239     //      sets up a try block before delegating parsing to its subject.
0240     //      When an exception is caught, the catch block then calls the
0241     //      HandlerT object. HandlerT may be a function or a functor (with
0242     //      an operator() member function) compatible with the interface:
0243     //
0244     //          error_status<T>
0245     //          handler(ScannerT const& scan, ErrorT error);
0246     //
0247     //      Where scan points to the scanner state prior to parsing and error
0248     //      is the error that arose (see parser_error). The handler must
0249     //      return an error_status<T> object (see above).
0250     //
0251     ///////////////////////////////////////////////////////////////////////////
0252     namespace impl
0253     {
0254         template <typename RT, typename ParserT, typename ScannerT>
0255         RT fallback_parser_parse(ParserT const& p, ScannerT const& scan);
0256     }
0257 
0258     template <typename ErrorDescrT, typename ParserT, typename HandlerT>
0259     struct fallback_parser
0260     :   public unary<ParserT,
0261         parser<fallback_parser<ErrorDescrT, ParserT, HandlerT> > >
0262     {
0263         typedef fallback_parser<ErrorDescrT, ParserT, HandlerT>
0264             self_t;
0265         typedef ErrorDescrT
0266             error_descr_t;
0267         typedef unary<ParserT, parser<self_t> >
0268             base_t;
0269         typedef unary_parser_category
0270             parser_category_t;
0271 
0272         fallback_parser(ParserT const& parser, HandlerT const& handler_)
0273         : base_t(parser), handler(handler_) {}
0274 
0275         template <typename ScannerT>
0276         struct result
0277         {
0278             typedef typename parser_result<ParserT, ScannerT>::type type;
0279         };
0280 
0281         template <typename ScannerT>
0282         typename parser_result<self_t, ScannerT>::type
0283         parse(ScannerT const& scan) const
0284         {
0285             typedef typename parser_result<self_t, ScannerT>::type result_t;
0286             return impl::fallback_parser_parse<result_t>(*this, scan);
0287         }
0288 
0289         HandlerT handler;
0290     };
0291 
0292     ///////////////////////////////////////////////////////////////////////////
0293     //
0294     //  guard class
0295     //
0296     //      fallback_parser objects are not instantiated directly. The guard
0297     //      class is used to indirectly create a fallback_parser object.
0298     //      guards are typically predeclared just like assertions (see the
0299     //      assertion class above; the example extends the previous example
0300     //      introduced in the assertion class above):
0301     //
0302     //          guard<Errors>   my_guard;
0303     //
0304     //      Errors, in this example is the error descriptor type we want to
0305     //      detect; This is essentially the ErrorDescrT template parameter
0306     //      of the fallback_parser class.
0307     //
0308     //      my_guard may now be used in a grammar declaration as:
0309     //
0310     //          my_guard(p)[h]
0311     //
0312     //      where p is a parser, h is a function or functor compatible with
0313     //      fallback_parser's HandlerT (see above).
0314     //
0315     ///////////////////////////////////////////////////////////////////////////
0316     template <typename ErrorDescrT, typename ParserT>
0317     struct guard_gen : public unary<ParserT, nil_t>
0318     {
0319         typedef guard<ErrorDescrT>      parser_generator_t;
0320         typedef unary_parser_category   parser_category_t;
0321 
0322         guard_gen(ParserT const& p)
0323         : unary<ParserT, nil_t>(p) {}
0324 
0325         template <typename HandlerT>
0326         fallback_parser<ErrorDescrT, ParserT, HandlerT>
0327         operator[](HandlerT const& handler) const
0328         {
0329             return fallback_parser<ErrorDescrT, ParserT, HandlerT>
0330                 (this->subject(), handler);
0331         }
0332     };
0333 
0334     template <typename ErrorDescrT>
0335     struct guard
0336     {
0337         template <typename ParserT>
0338         struct result
0339         {
0340             typedef guard_gen<ErrorDescrT, ParserT> type;
0341         };
0342 
0343         template <typename ParserT>
0344         static guard_gen<ErrorDescrT, ParserT>
0345         generate(ParserT const& parser)
0346         {
0347             return guard_gen<ErrorDescrT, ParserT>(parser);
0348         }
0349 
0350         template <typename ParserT>
0351         guard_gen<ErrorDescrT, ParserT>
0352         operator()(ParserT const& parser) const
0353         {
0354             return guard_gen<ErrorDescrT, ParserT>(parser);
0355         }
0356     };
0357 
0358 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0359 
0360 }} // namespace BOOST_SPIRIT_CLASSIC_NS
0361 
0362 #include <boost/spirit/home/classic/error_handling/impl/exceptions.ipp>
0363 #endif
0364