error_handling_fwd.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #ifndef BOOST_PARSER_ERROR_HANDLING_FWD_HPP
  2. #define BOOST_PARSER_ERROR_HANDLING_FWD_HPP
  3. #include <boost/parser/config.hpp>
  4. #include <boost/parser/detail/text/transcode_view.hpp>
  5. #include <iostream>
  6. #include <string_view>
  7. namespace boost { namespace parser {
  8. /** The possible actions to take when a parse error is handled by an error
  9. handler. */
  10. enum class error_handler_result {
  11. fail, /// Fail the top-level parse.
  12. rethrow /// Re-throw the parse error exception.
  13. };
  14. /** The exception thrown when a parse error is encountered, consisting of
  15. an iterator to the point of failure, and the name of the failed parser
  16. or rule in `what()`. */
  17. template<typename Iter>
  18. struct parse_error : std::runtime_error
  19. {
  20. parse_error(Iter it, std::string const & msg) :
  21. runtime_error(msg), iter(it)
  22. {}
  23. Iter iter;
  24. };
  25. /** A position within a line, consisting of an iterator to the start of
  26. the line, the line number, and the column number. */
  27. template<typename Iter>
  28. struct line_position
  29. {
  30. Iter line_start;
  31. int64_t line_number;
  32. int64_t column_number;
  33. };
  34. /** Writes a formatted message (meaning prefixed with the file name, line,
  35. and column number) to `os`. */
  36. template<typename Iter, typename Sentinel>
  37. std::ostream & write_formatted_message(
  38. std::ostream & os,
  39. std::string_view filename,
  40. Iter first,
  41. Iter it,
  42. Sentinel last,
  43. std::string_view message,
  44. int64_t preferred_max_line_length = 80,
  45. int64_t max_after_caret = 40);
  46. #if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN)
  47. /** Writes a formatted message (meaning prefixed with the file name, line,
  48. and column number) to `os`. This overload is Windows-only. */
  49. template<typename Iter, typename Sentinel>
  50. std::ostream & write_formatted_message(
  51. std::ostream & os,
  52. std::wstring_view filename,
  53. Iter first,
  54. Iter it,
  55. Sentinel last,
  56. std::string_view message,
  57. int64_t preferred_max_line_length = 80,
  58. int64_t max_after_caret = 40);
  59. #endif
  60. /** Writes a formatted parse-expectation failure (meaning prefixed with
  61. the file name, line, and column number) to `os`. */
  62. template<typename Iter, typename Sentinel>
  63. std::ostream & write_formatted_expectation_failure_error_message(
  64. std::ostream & os,
  65. std::string_view filename,
  66. Iter first,
  67. Sentinel last,
  68. parse_error<Iter> const & e,
  69. int64_t preferred_max_line_length = 80,
  70. int64_t max_after_caret = 40);
  71. #if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN)
  72. /** Writes a formatted parse-expectation failure (meaning prefixed with
  73. the file name, line, and column number) to `os`. This overload is
  74. Windows-only. */
  75. template<typename Iter, typename Sentinel>
  76. std::ostream & write_formatted_expectation_failure_error_message(
  77. std::ostream & os,
  78. std::wstring_view filename,
  79. Iter first,
  80. Sentinel last,
  81. parse_error<Iter> const & e,
  82. int64_t preferred_max_line_length = 80,
  83. int64_t max_after_caret = 40);
  84. #endif
  85. /** The kinds of diagnostics that can be handled by an error handler. */
  86. enum class diagnostic_kind {
  87. error, /// An error diagnostic.
  88. warning /// A warning diagnostic.
  89. };
  90. /** The error handler used when the user does not specify a custom one.
  91. This error handler prints warnings and errors to `std::cerr`, and does
  92. not have an associated filename. */
  93. struct default_error_handler
  94. {
  95. constexpr default_error_handler() = default;
  96. /** Handles a `parse_error` exception thrown during parsing. A
  97. formatted parse-expectation failure is printed to `std::cerr`.
  98. Always returns `error_handler_result::fail`. */
  99. template<typename Iter, typename Sentinel>
  100. error_handler_result operator()(
  101. Iter first, Sentinel last, parse_error<Iter> const & e) const;
  102. /** Prints `message` to `std::cerr`. The diagnostic is printed with
  103. the given `kind`, indicating the location as being at `it`. This
  104. must be called within a parser semantic action, providing the
  105. parse context. */
  106. //[ error_handler_api_1
  107. template<typename Context, typename Iter>
  108. void diagnose(
  109. diagnostic_kind kind,
  110. std::string_view message,
  111. Context const & context,
  112. Iter it) const;
  113. //]
  114. /** Prints `message` to `std::cerr`. The diagnostic is printed with
  115. the given `kind`, at no particular location. This must be called
  116. within a parser semantic action, providing the parse context. */
  117. //[ error_handler_api_2
  118. template<typename Context>
  119. void diagnose(
  120. diagnostic_kind kind,
  121. std::string_view message,
  122. Context const & context) const;
  123. //]
  124. };
  125. /** Prints warnings and errors to the `std::ostream`s provided by the
  126. user, or `std::cerr` if neither stream is specified. If a filename is
  127. provided, that is used to print all diagnostics. */
  128. struct stream_error_handler
  129. {
  130. stream_error_handler() : err_os_(&std::cerr), warn_os_(err_os_) {}
  131. stream_error_handler(std::string_view filename) :
  132. filename_(filename), err_os_(&std::cerr), warn_os_(err_os_)
  133. {}
  134. stream_error_handler(std::string_view filename, std::ostream & errors) :
  135. filename_(filename), err_os_(&errors), warn_os_(&errors)
  136. {}
  137. stream_error_handler(
  138. std::string_view filename,
  139. std::ostream & errors,
  140. std::ostream & warnings) :
  141. filename_(filename), err_os_(&errors), warn_os_(&warnings)
  142. {}
  143. #if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN)
  144. /** This overload is Windows-only. */
  145. stream_error_handler(std::wstring_view filename) :
  146. err_os_(&std::cerr), warn_os_(err_os_)
  147. {
  148. auto const r = filename | detail::text::as_utf8;
  149. filename_.assign(r.begin(), r.end());
  150. }
  151. /** This overload is Windows-only. */
  152. stream_error_handler(
  153. std::wstring_view filename, std::ostream & errors) :
  154. err_os_(&errors), warn_os_(&errors)
  155. {
  156. auto const r = filename | detail::text::as_utf8;
  157. filename_.assign(r.begin(), r.end());
  158. }
  159. /** This overload is Windows-only. */
  160. stream_error_handler(
  161. std::wstring_view filename,
  162. std::ostream & errors,
  163. std::ostream & warnings) :
  164. err_os_(&errors), warn_os_(&warnings)
  165. {
  166. auto const r = filename | detail::text::as_utf8;
  167. filename_.assign(r.begin(), r.end());
  168. }
  169. #endif
  170. /** Handles a `parse_error` exception thrown during parsing. A
  171. formatted parse-expectation failure is printed to `*err_os_` when
  172. `err_os_` is non-null, or `std::cerr` otherwise. Always returns
  173. `error_handler_result::fail`. */
  174. template<typename Iter, typename Sentinel>
  175. error_handler_result
  176. operator()(Iter first, Sentinel last, parse_error<Iter> const & e) const;
  177. /** Let `std::ostream * s = kind == diagnostic_kind::error : err_os_ :
  178. warn_os_`; prints `message` to `*s` when `s` is non-null, or
  179. `std::cerr` otherwise. The diagnostic is printed with the given
  180. `kind`, indicating the location as being at `it`. This must be
  181. called within a parser semantic action, providing the parse
  182. context. */
  183. template<typename Context, typename Iter>
  184. void diagnose(
  185. diagnostic_kind kind,
  186. std::string_view message,
  187. Context const & context,
  188. Iter it) const;
  189. /** Let `std::ostream * s = kind == diagnostic_kind::error : err_os_ :
  190. warn_os_`; prints `message` to `*s` when `s` is non-null, or
  191. `std::cerr` otherwise. The diagnostic is printed with the given
  192. `kind`, at no particular location. This must be called within a
  193. parser semantic action, providing the parse context. */
  194. template<typename Context>
  195. void diagnose(
  196. diagnostic_kind kind,
  197. std::string_view message,
  198. Context const & context) const;
  199. private:
  200. std::string filename_;
  201. std::ostream * err_os_;
  202. std::ostream * warn_os_;
  203. };
  204. }}
  205. #endif