exceptions.hpp 13 KB

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