Chris@16: /*============================================================================= Chris@16: Boost.Wave: A Standard compliant C++ preprocessor library Chris@16: Chris@16: http://www.boost.org/ Chris@16: Chris@16: Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost Chris@16: Software License, Version 1.0. (See accompanying file Chris@16: LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: Chris@16: #if !defined(CPPLEXER_EXCEPTIONS_HPP_1A09DE1A_6D1F_4091_AF7F_5F13AB0D31AB_INCLUDED) Chris@16: #define CPPLEXER_EXCEPTIONS_HPP_1A09DE1A_6D1F_4091_AF7F_5F13AB0D31AB_INCLUDED Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: // this must occur after all of the includes and before any code appears Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_PREFIX Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // helper macro for throwing exceptions Chris@16: #if !defined(BOOST_WAVE_LEXER_THROW) Chris@16: #ifdef BOOST_NO_STRINGSTREAM Chris@16: #include Chris@16: #define BOOST_WAVE_LEXER_THROW(cls, code, msg, line, column, name) \ Chris@16: { \ Chris@16: using namespace boost::wave; \ Chris@16: std::strstream stream; \ Chris@16: stream << cls::severity_text(cls::code) << ": " \ Chris@16: << cls::error_text(cls::code); \ Chris@16: if ((msg)[0] != 0) stream << ": " << (msg); \ Chris@16: stream << std::ends; \ Chris@16: std::string throwmsg = stream.str(); stream.freeze(false); \ Chris@16: boost::throw_exception(cls(throwmsg.c_str(), cls::code, line, column, \ Chris@16: name)); \ Chris@16: } \ Chris@16: /**/ Chris@16: #else Chris@16: #include Chris@16: #define BOOST_WAVE_LEXER_THROW(cls, code, msg, line, column, name) \ Chris@16: { \ Chris@16: using namespace boost::wave; \ Chris@16: std::stringstream stream; \ Chris@16: stream << cls::severity_text(cls::code) << ": " \ Chris@16: << cls::error_text(cls::code); \ Chris@16: if ((msg)[0] != 0) stream << ": " << (msg); \ Chris@16: stream << std::ends; \ Chris@16: boost::throw_exception(cls(stream.str().c_str(), cls::code, line, column, \ Chris@16: name)); \ Chris@16: } \ Chris@16: /**/ Chris@16: #endif // BOOST_NO_STRINGSTREAM Chris@16: #endif // BOOST_WAVE_LEXER_THROW Chris@16: Chris@16: #if !defined(BOOST_WAVE_LEXER_THROW_VAR) Chris@16: #ifdef BOOST_NO_STRINGSTREAM Chris@16: #include Chris@16: #define BOOST_WAVE_LEXER_THROW_VAR(cls, codearg, msg, line, column, name) \ Chris@16: { \ Chris@16: using namespace boost::wave; \ Chris@16: cls::error_code code = static_cast(codearg); \ Chris@16: std::strstream stream; \ Chris@16: stream << cls::severity_text(code) << ": " \ Chris@16: << cls::error_text(code); \ Chris@16: if ((msg)[0] != 0) stream << ": " << (msg); \ Chris@16: stream << std::ends; \ Chris@16: std::string throwmsg = stream.str(); stream.freeze(false); \ Chris@16: boost::throw_exception(cls(throwmsg.c_str(), code, line, column, \ Chris@16: name)); \ Chris@16: } \ Chris@16: /**/ Chris@16: #else Chris@16: #include Chris@16: #define BOOST_WAVE_LEXER_THROW_VAR(cls, codearg, msg, line, column, name) \ Chris@16: { \ Chris@16: using namespace boost::wave; \ Chris@16: cls::error_code code = static_cast(codearg); \ Chris@16: std::stringstream stream; \ Chris@16: stream << cls::severity_text(code) << ": " \ Chris@16: << cls::error_text(code); \ Chris@16: if ((msg)[0] != 0) stream << ": " << (msg); \ Chris@16: stream << std::ends; \ Chris@16: boost::throw_exception(cls(stream.str().c_str(), code, line, column, \ Chris@16: name)); \ Chris@16: } \ Chris@16: /**/ Chris@16: #endif // BOOST_NO_STRINGSTREAM Chris@16: #endif // BOOST_WAVE_LEXER_THROW Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { Chris@16: namespace wave { Chris@16: namespace cpplexer { Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // exception severity Chris@16: namespace util { Chris@16: Chris@16: enum severity { Chris@16: severity_remark = 0, Chris@16: severity_warning, Chris@16: severity_error, Chris@16: severity_fatal Chris@16: }; Chris@16: Chris@16: inline char const * Chris@16: get_severity(severity level) Chris@16: { Chris@16: static char const *severity_text[] = Chris@16: { Chris@16: "remark", // severity_remark Chris@16: "warning", // severity_warning Chris@16: "error", // severity_error Chris@16: "fatal error" // severity_fatal Chris@16: }; Chris@16: BOOST_ASSERT(severity_remark <= level && level <= severity_fatal); Chris@16: return severity_text[level]; Chris@16: } Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // cpplexer_exception, the base class for all specific C++ lexer exceptions Chris@16: class BOOST_SYMBOL_VISIBLE cpplexer_exception Chris@16: : public std::exception Chris@16: { Chris@16: public: Chris@16: cpplexer_exception(std::size_t line_, std::size_t column_, char const *filename_) throw() Chris@16: : line(line_), column(column_) Chris@16: { Chris@16: unsigned int off = 0; Chris@16: while (off < sizeof(filename)-1 && *filename_) Chris@16: filename[off++] = *filename_++; Chris@16: filename[off] = 0; Chris@16: } Chris@16: ~cpplexer_exception() throw() {} Chris@16: Chris@16: virtual char const *what() const throw() = 0; // to be overloaded Chris@16: virtual char const *description() const throw() = 0; Chris@16: virtual int get_errorcode() const throw() = 0; Chris@16: virtual int get_severity() const throw() = 0; Chris@16: virtual bool is_recoverable() const throw() = 0; Chris@16: Chris@16: std::size_t line_no() const throw() { return line; } Chris@16: std::size_t column_no() const throw() { return column; } Chris@16: char const *file_name() const throw() { return filename; } Chris@16: Chris@16: protected: Chris@16: char filename[512]; Chris@16: std::size_t line; Chris@16: std::size_t column; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // lexing_exception error Chris@16: class BOOST_SYMBOL_VISIBLE lexing_exception : Chris@16: public cpplexer_exception Chris@16: { Chris@16: public: Chris@16: enum error_code { Chris@16: unexpected_error = 0, Chris@16: universal_char_invalid = 1, Chris@16: universal_char_base_charset = 2, Chris@16: universal_char_not_allowed = 3, Chris@16: invalid_long_long_literal = 4, Chris@16: generic_lexing_error = 5, Chris@16: generic_lexing_warning = 6 Chris@16: }; Chris@16: Chris@16: lexing_exception(char const *what_, error_code code, std::size_t line_, Chris@16: std::size_t column_, char const *filename_) throw() Chris@16: : cpplexer_exception(line_, column_, filename_), Chris@16: level(severity_level(code)), code(code) Chris@16: { Chris@16: unsigned int off = 0; Chris@16: while (off < sizeof(buffer)-1 && *what_) Chris@16: buffer[off++] = *what_++; Chris@16: buffer[off] = 0; Chris@16: } Chris@16: ~lexing_exception() throw() {} Chris@16: Chris@16: virtual char const *what() const throw() Chris@16: { Chris@16: return "boost::wave::lexing_exception"; Chris@16: } Chris@16: virtual char const *description() const throw() Chris@16: { Chris@16: return buffer; Chris@16: } Chris@16: virtual int get_severity() const throw() Chris@16: { Chris@16: return level; Chris@16: } Chris@16: virtual int get_errorcode() const throw() Chris@16: { Chris@16: return code; Chris@16: } Chris@16: virtual bool is_recoverable() const throw() Chris@16: { Chris@16: switch (get_errorcode()) { Chris@16: case lexing_exception::universal_char_invalid: Chris@16: case lexing_exception::universal_char_base_charset: Chris@16: case lexing_exception::universal_char_not_allowed: Chris@16: case lexing_exception::invalid_long_long_literal: Chris@16: case lexing_exception::generic_lexing_warning: Chris@16: case lexing_exception::generic_lexing_error: Chris@16: return true; // for now allow all exceptions to be recoverable Chris@16: Chris@16: case lexing_exception::unexpected_error: Chris@16: default: Chris@16: break; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: static char const *error_text(int code) Chris@16: { Chris@16: // error texts in this array must appear in the same order as the items in Chris@16: // the error enum above Chris@16: static char const *preprocess_exception_errors[] = { Chris@16: "unexpected error (should not happen)", // unexpected_error Chris@16: "universal character name specifies an invalid character", // universal_char_invalid Chris@16: "a universal character name cannot designate a character in the " Chris@16: "basic character set", // universal_char_base_charset Chris@16: "this universal character is not allowed in an identifier", // universal_char_not_allowed Chris@16: "long long suffixes are not allowed in pure C++ mode, " Chris@16: "enable long_long mode to allow these", // invalid_long_long_literal Chris@16: "generic lexer error", // generic_lexing_error Chris@16: "generic lexer warning" // generic_lexing_warning Chris@16: }; Chris@16: return preprocess_exception_errors[code]; Chris@16: } Chris@16: Chris@16: static util::severity severity_level(int code) Chris@16: { Chris@16: static util::severity preprocess_exception_severity[] = { Chris@16: util::severity_fatal, // unexpected_error Chris@16: util::severity_error, // universal_char_invalid Chris@16: util::severity_error, // universal_char_base_charset Chris@16: util::severity_error, // universal_char_not_allowed Chris@16: util::severity_warning, // invalid_long_long_literal Chris@16: util::severity_error, // generic_lexing_error Chris@16: util::severity_warning // invalid_long_long_literal Chris@16: }; Chris@16: return preprocess_exception_severity[code]; Chris@16: } Chris@16: static char const *severity_text(int code) Chris@16: { Chris@16: return util::get_severity(severity_level(code)); Chris@16: } Chris@16: Chris@16: private: Chris@16: char buffer[512]; Chris@16: util::severity level; Chris@16: error_code code; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // The is_recoverable() function allows to decide, whether it is possible Chris@16: // simply to continue after a given exception was thrown by Wave. Chris@16: // Chris@16: // This is kind of a hack to allow to recover from certain errors as long as Chris@16: // Wave doesn't provide better means of error recovery. Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: inline bool Chris@16: is_recoverable(lexing_exception const& e) Chris@16: { Chris@16: return e.is_recoverable(); Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: } // namespace cpplexer Chris@16: } // namespace wave Chris@16: } // namespace boost Chris@16: Chris@16: // the suffix header occurs after all of the code Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_SUFFIX Chris@16: #endif Chris@16: Chris@16: #endif // !defined(CPPLEXER_EXCEPTIONS_HPP_1A09DE1A_6D1F_4091_AF7F_5F13AB0D31AB_INCLUDED)