123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- /*=============================================================================
- Copyright (c) 2001-2003 Joel de Guzman
- http://spirit.sourceforge.net/
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- =============================================================================*/
- #ifndef BOOST_SPIRIT_EXCEPTIONS_HPP
- #define BOOST_SPIRIT_EXCEPTIONS_HPP
- #include <boost/config.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/spirit/home/classic/namespace.hpp>
- #include <boost/spirit/home/classic/core/parser.hpp>
- #include <boost/spirit/home/classic/core/composite/composite.hpp>
- #include <exception>
- #include <boost/spirit/home/classic/error_handling/exceptions_fwd.hpp>
- namespace boost { namespace spirit {
- BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
- ///////////////////////////////////////////////////////////////////////////
- //
- // parser_error_base class
- //
- // This is the base class of parser_error (see below). This may be
- // used to catch any type of parser error.
- //
- // This exception shouldn't propagate outside the parser. However to
- // avoid quirks of many platforms/implementations which fall outside
- // the C++ standard, we derive parser_error_base from std::exception
- // to allow a single catch handler to catch all exceptions.
- //
- ///////////////////////////////////////////////////////////////////////////
- class BOOST_SYMBOL_VISIBLE parser_error_base : public std::exception
- {
- protected:
- parser_error_base() {}
- virtual ~parser_error_base() BOOST_NOEXCEPT_OR_NOTHROW {}
- public:
- parser_error_base(parser_error_base const& rhs)
- : std::exception(rhs) {}
- parser_error_base& operator=(parser_error_base const&)
- {
- return *this;
- }
- };
- ///////////////////////////////////////////////////////////////////////////
- //
- // parser_error class
- //
- // Generic parser exception class. This is the base class for all
- // parser exceptions. The exception holds the iterator position
- // where the error was encountered in its member variable "where".
- // The parser_error also holds information regarding the error
- // (error descriptor) in its member variable "descriptor".
- //
- // The throw_ function creates and throws a parser_error given
- // an iterator and an error descriptor.
- //
- ///////////////////////////////////////////////////////////////////////////
- template <typename ErrorDescrT, typename IteratorT>
- struct parser_error : public parser_error_base
- {
- typedef ErrorDescrT error_descr_t;
- typedef IteratorT iterator_t;
- parser_error(IteratorT where_, ErrorDescrT descriptor_)
- : where(where_), descriptor(descriptor_) {}
- parser_error(parser_error const& rhs)
- : parser_error_base(rhs)
- , where(rhs.where), descriptor(rhs.descriptor) {}
- parser_error&
- operator=(parser_error const& rhs)
- {
- where = rhs.where;
- descriptor = rhs.descriptor;
- return *this;
- }
- virtual
- ~parser_error() BOOST_NOEXCEPT_OR_NOTHROW {}
- virtual const char*
- what() const BOOST_NOEXCEPT_OR_NOTHROW
- {
- return "BOOST_SPIRIT_CLASSIC_NS::parser_error";
- }
- IteratorT where;
- ErrorDescrT descriptor;
- };
- //////////////////////////////////
- template <typename ErrorDescrT, typename IteratorT>
- inline void
- throw_(IteratorT where, ErrorDescrT descriptor)
- {
- boost::throw_exception(
- parser_error<ErrorDescrT, IteratorT>(where, descriptor));
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // assertive_parser class
- //
- // An assertive_parser class is a parser that throws an exception
- // in response to a parsing failure. The assertive_parser throws a
- // parser_error exception rather than returning an unsuccessful
- // match to signal that the parser failed to match the input.
- //
- ///////////////////////////////////////////////////////////////////////////
- template <typename ErrorDescrT, typename ParserT>
- struct assertive_parser
- : public unary<ParserT, parser<assertive_parser<ErrorDescrT, ParserT> > >
- {
- typedef assertive_parser<ErrorDescrT, ParserT> self_t;
- typedef unary<ParserT, parser<self_t> > base_t;
- typedef unary_parser_category parser_category_t;
- assertive_parser(ParserT const& parser, ErrorDescrT descriptor_)
- : base_t(parser), descriptor(descriptor_) {}
- template <typename ScannerT>
- struct result
- {
- typedef typename parser_result<ParserT, ScannerT>::type type;
- };
- template <typename ScannerT>
- typename parser_result<self_t, ScannerT>::type
- parse(ScannerT const& scan) const
- {
- typedef typename parser_result<ParserT, ScannerT>::type result_t;
- result_t hit = this->subject().parse(scan);
- if (!hit)
- {
- throw_(scan.first, descriptor);
- }
- return hit;
- }
- ErrorDescrT descriptor;
- };
- ///////////////////////////////////////////////////////////////////////////
- //
- // assertion class
- //
- // assertive_parsers are never instantiated directly. The assertion
- // class is used to indirectly create an assertive_parser object.
- // Before declaring the grammar, we declare some assertion objects.
- // Examples:
- //
- // enum Errors
- // {
- // program_expected, begin_expected, end_expected
- // };
- //
- // assertion<Errors> expect_program(program_expected);
- // assertion<Errors> expect_begin(begin_expected);
- // assertion<Errors> expect_end(end_expected);
- //
- // Now, we can use these assertions as wrappers around parsers:
- //
- // expect_end(str_p("end"))
- //
- // Take note that although the example uses enums to hold the
- // information regarding the error (error desccriptor), we are free
- // to use other types such as integers and strings. Enums are
- // convenient for error handlers to easily catch since C++ treats
- // enums as unique types.
- //
- ///////////////////////////////////////////////////////////////////////////
- template <typename ErrorDescrT>
- struct assertion
- {
- assertion(ErrorDescrT descriptor_)
- : descriptor(descriptor_) {}
- template <typename ParserT>
- assertive_parser<ErrorDescrT, ParserT>
- operator()(ParserT const& parser) const
- {
- return assertive_parser<ErrorDescrT, ParserT>(parser, descriptor);
- }
- ErrorDescrT descriptor;
- };
- ///////////////////////////////////////////////////////////////////////////
- //
- // error_status<T>
- //
- // Where T is an attribute type compatible with the match attribute
- // of the fallback_parser's subject (defaults to nil_t). The class
- // error_status reports the result of an error handler (see
- // fallback_parser). result can be one of:
- //
- // fail: quit and fail (return a no_match)
- // retry: attempt error recovery, possibly moving the scanner
- // accept: force success returning a matching length, moving
- // the scanner appropriately and returning an attribute
- // value
- // rethrow: rethrows the error.
- //
- ///////////////////////////////////////////////////////////////////////////
- template <typename T>
- struct error_status
- {
- enum result_t { fail, retry, accept, rethrow };
- error_status(
- result_t result_ = fail,
- std::ptrdiff_t length_ = -1,
- T const& value_ = T())
- : result(result_), length(length_), value(value_) {}
- result_t result;
- std::ptrdiff_t length;
- T value;
- };
- ///////////////////////////////////////////////////////////////////////////
- //
- // fallback_parser class
- //
- // Handles exceptions of type parser_error<ErrorDescrT, IteratorT>
- // thrown somewhere inside its embedded ParserT object. The class
- // sets up a try block before delegating parsing to its subject.
- // When an exception is caught, the catch block then calls the
- // HandlerT object. HandlerT may be a function or a functor (with
- // an operator() member function) compatible with the interface:
- //
- // error_status<T>
- // handler(ScannerT const& scan, ErrorT error);
- //
- // Where scan points to the scanner state prior to parsing and error
- // is the error that arose (see parser_error). The handler must
- // return an error_status<T> object (see above).
- //
- ///////////////////////////////////////////////////////////////////////////
- namespace impl
- {
- template <typename RT, typename ParserT, typename ScannerT>
- RT fallback_parser_parse(ParserT const& p, ScannerT const& scan);
- }
- template <typename ErrorDescrT, typename ParserT, typename HandlerT>
- struct fallback_parser
- : public unary<ParserT,
- parser<fallback_parser<ErrorDescrT, ParserT, HandlerT> > >
- {
- typedef fallback_parser<ErrorDescrT, ParserT, HandlerT>
- self_t;
- typedef ErrorDescrT
- error_descr_t;
- typedef unary<ParserT, parser<self_t> >
- base_t;
- typedef unary_parser_category
- parser_category_t;
- fallback_parser(ParserT const& parser, HandlerT const& handler_)
- : base_t(parser), handler(handler_) {}
- template <typename ScannerT>
- struct result
- {
- typedef typename parser_result<ParserT, ScannerT>::type type;
- };
- template <typename ScannerT>
- typename parser_result<self_t, ScannerT>::type
- parse(ScannerT const& scan) const
- {
- typedef typename parser_result<self_t, ScannerT>::type result_t;
- return impl::fallback_parser_parse<result_t>(*this, scan);
- }
- HandlerT handler;
- };
- ///////////////////////////////////////////////////////////////////////////
- //
- // guard class
- //
- // fallback_parser objects are not instantiated directly. The guard
- // class is used to indirectly create a fallback_parser object.
- // guards are typically predeclared just like assertions (see the
- // assertion class above; the example extends the previous example
- // introduced in the assertion class above):
- //
- // guard<Errors> my_guard;
- //
- // Errors, in this example is the error descriptor type we want to
- // detect; This is essentially the ErrorDescrT template parameter
- // of the fallback_parser class.
- //
- // my_guard may now be used in a grammar declaration as:
- //
- // my_guard(p)[h]
- //
- // where p is a parser, h is a function or functor compatible with
- // fallback_parser's HandlerT (see above).
- //
- ///////////////////////////////////////////////////////////////////////////
- template <typename ErrorDescrT, typename ParserT>
- struct guard_gen : public unary<ParserT, nil_t>
- {
- typedef guard<ErrorDescrT> parser_generator_t;
- typedef unary_parser_category parser_category_t;
- guard_gen(ParserT const& p)
- : unary<ParserT, nil_t>(p) {}
- template <typename HandlerT>
- fallback_parser<ErrorDescrT, ParserT, HandlerT>
- operator[](HandlerT const& handler) const
- {
- return fallback_parser<ErrorDescrT, ParserT, HandlerT>
- (this->subject(), handler);
- }
- };
- template <typename ErrorDescrT>
- struct guard
- {
- template <typename ParserT>
- struct result
- {
- typedef guard_gen<ErrorDescrT, ParserT> type;
- };
- template <typename ParserT>
- static guard_gen<ErrorDescrT, ParserT>
- generate(ParserT const& parser)
- {
- return guard_gen<ErrorDescrT, ParserT>(parser);
- }
- template <typename ParserT>
- guard_gen<ErrorDescrT, ParserT>
- operator()(ParserT const& parser) const
- {
- return guard_gen<ErrorDescrT, ParserT>(parser);
- }
- };
- BOOST_SPIRIT_CLASSIC_NAMESPACE_END
- }} // namespace BOOST_SPIRIT_CLASSIC_NS
- #include <boost/spirit/home/classic/error_handling/impl/exceptions.ipp>
- #endif
|