#ifndef BOOST_PARSER_ERROR_HANDLING_FWD_HPP #define BOOST_PARSER_ERROR_HANDLING_FWD_HPP #include #include #include #include namespace boost { namespace parser { /** The possible actions to take when a parse error is handled by an error handler. */ enum class error_handler_result { fail, /// Fail the top-level parse. rethrow /// Re-throw the parse error exception. }; /** The exception thrown when a parse error is encountered, consisting of an iterator to the point of failure, and the name of the failed parser or rule in `what()`. */ template struct parse_error : std::runtime_error { parse_error(Iter it, std::string const & msg) : runtime_error(msg), iter(it) {} Iter iter; }; /** A position within a line, consisting of an iterator to the start of the line, the line number, and the column number. */ template struct line_position { Iter line_start; int64_t line_number; int64_t column_number; }; /** Writes a formatted message (meaning prefixed with the file name, line, and column number) to `os`. */ template std::ostream & write_formatted_message( std::ostream & os, std::string_view filename, Iter first, Iter it, Sentinel last, std::string_view message, int64_t preferred_max_line_length = 80, int64_t max_after_caret = 40); #if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN) /** Writes a formatted message (meaning prefixed with the file name, line, and column number) to `os`. This overload is Windows-only. */ template std::ostream & write_formatted_message( std::ostream & os, std::wstring_view filename, Iter first, Iter it, Sentinel last, std::string_view message, int64_t preferred_max_line_length = 80, int64_t max_after_caret = 40); #endif /** Writes a formatted parse-expectation failure (meaning prefixed with the file name, line, and column number) to `os`. */ template std::ostream & write_formatted_expectation_failure_error_message( std::ostream & os, std::string_view filename, Iter first, Sentinel last, parse_error const & e, int64_t preferred_max_line_length = 80, int64_t max_after_caret = 40); #if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN) /** Writes a formatted parse-expectation failure (meaning prefixed with the file name, line, and column number) to `os`. This overload is Windows-only. */ template std::ostream & write_formatted_expectation_failure_error_message( std::ostream & os, std::wstring_view filename, Iter first, Sentinel last, parse_error const & e, int64_t preferred_max_line_length = 80, int64_t max_after_caret = 40); #endif /** The kinds of diagnostics that can be handled by an error handler. */ enum class diagnostic_kind { error, /// An error diagnostic. warning /// A warning diagnostic. }; /** The error handler used when the user does not specify a custom one. This error handler prints warnings and errors to `std::cerr`, and does not have an associated filename. */ struct default_error_handler { constexpr default_error_handler() = default; /** Handles a `parse_error` exception thrown during parsing. A formatted parse-expectation failure is printed to `std::cerr`. Always returns `error_handler_result::fail`. */ template error_handler_result operator()( Iter first, Sentinel last, parse_error const & e) const; /** Prints `message` to `std::cerr`. The diagnostic is printed with the given `kind`, indicating the location as being at `it`. This must be called within a parser semantic action, providing the parse context. */ //[ error_handler_api_1 template void diagnose( diagnostic_kind kind, std::string_view message, Context const & context, Iter it) const; //] /** Prints `message` to `std::cerr`. The diagnostic is printed with the given `kind`, at no particular location. This must be called within a parser semantic action, providing the parse context. */ //[ error_handler_api_2 template void diagnose( diagnostic_kind kind, std::string_view message, Context const & context) const; //] }; /** Prints warnings and errors to the `std::ostream`s provided by the user, or `std::cerr` if neither stream is specified. If a filename is provided, that is used to print all diagnostics. */ struct stream_error_handler { stream_error_handler() : err_os_(&std::cerr), warn_os_(err_os_) {} stream_error_handler(std::string_view filename) : filename_(filename), err_os_(&std::cerr), warn_os_(err_os_) {} stream_error_handler(std::string_view filename, std::ostream & errors) : filename_(filename), err_os_(&errors), warn_os_(&errors) {} stream_error_handler( std::string_view filename, std::ostream & errors, std::ostream & warnings) : filename_(filename), err_os_(&errors), warn_os_(&warnings) {} #if defined(_MSC_VER) || defined(BOOST_PARSER_DOXYGEN) /** This overload is Windows-only. */ stream_error_handler(std::wstring_view filename) : err_os_(&std::cerr), warn_os_(err_os_) { auto const r = filename | detail::text::as_utf8; filename_.assign(r.begin(), r.end()); } /** This overload is Windows-only. */ stream_error_handler( std::wstring_view filename, std::ostream & errors) : err_os_(&errors), warn_os_(&errors) { auto const r = filename | detail::text::as_utf8; filename_.assign(r.begin(), r.end()); } /** This overload is Windows-only. */ stream_error_handler( std::wstring_view filename, std::ostream & errors, std::ostream & warnings) : err_os_(&errors), warn_os_(&warnings) { auto const r = filename | detail::text::as_utf8; filename_.assign(r.begin(), r.end()); } #endif /** Handles a `parse_error` exception thrown during parsing. A formatted parse-expectation failure is printed to `*err_os_` when `err_os_` is non-null, or `std::cerr` otherwise. Always returns `error_handler_result::fail`. */ template error_handler_result operator()(Iter first, Sentinel last, parse_error const & e) const; /** Let `std::ostream * s = kind == diagnostic_kind::error : err_os_ : warn_os_`; prints `message` to `*s` when `s` is non-null, or `std::cerr` otherwise. The diagnostic is printed with the given `kind`, indicating the location as being at `it`. This must be called within a parser semantic action, providing the parse context. */ template void diagnose( diagnostic_kind kind, std::string_view message, Context const & context, Iter it) const; /** Let `std::ostream * s = kind == diagnostic_kind::error : err_os_ : warn_os_`; prints `message` to `*s` when `s` is non-null, or `std::cerr` otherwise. The diagnostic is printed with the given `kind`, at no particular location. This must be called within a parser semantic action, providing the parse context. */ template void diagnose( diagnostic_kind kind, std::string_view message, Context const & context) const; private: std::string filename_; std::ostream * err_os_; std::ostream * warn_os_; }; }} #endif