1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3
4 http://www.boost.org/
5
6 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
7 Software License, Version 1.0. (See accompanying file
8 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10
11 #if !defined(BOOST_CPPLEXER_EXCEPTIONS_HPP_1A09DE1A_6D1F_4091_AF7F_5F13AB0D31AB_INCLUDED)
12 #define BOOST_CPPLEXER_EXCEPTIONS_HPP_1A09DE1A_6D1F_4091_AF7F_5F13AB0D31AB_INCLUDED
13
14 #include <exception>
15 #include <string>
16
17 #include <boost/assert.hpp>
18 #include <boost/config.hpp>
19 #include <boost/throw_exception.hpp>
20
21 #include <boost/wave/wave_config.hpp>
22
23 // this must occur after all of the includes and before any code appears
24 #ifdef BOOST_HAS_ABI_HEADERS
25 #include BOOST_ABI_PREFIX
26 #endif
27
28 ///////////////////////////////////////////////////////////////////////////////
29 // helper macro for throwing exceptions
30 #if !defined(BOOST_WAVE_LEXER_THROW)
31 #ifdef BOOST_NO_STRINGSTREAM
32 #include <strstream>
33 #define BOOST_WAVE_LEXER_THROW(cls, code, msg, line, column, name) \
34 { \
35 using namespace boost::wave; \
36 std::strstream stream; \
37 stream << cls::severity_text(cls::code) << ": " \
38 << cls::error_text(cls::code); \
39 if ((msg)[0] != 0) stream << ": " << (msg); \
40 stream << std::ends; \
41 std::string throwmsg = stream.str(); stream.freeze(false); \
42 boost::throw_exception(cls(throwmsg.c_str(), cls::code, line, column, \
43 name)); \
44 } \
45 /**/
46 #else
47 #include <sstream>
48 #define BOOST_WAVE_LEXER_THROW(cls, code, msg, line, column, name) \
49 { \
50 using namespace boost::wave; \
51 std::stringstream stream; \
52 stream << cls::severity_text(cls::code) << ": " \
53 << cls::error_text(cls::code); \
54 if ((msg)[0] != 0) stream << ": " << (msg); \
55 stream << std::ends; \
56 boost::throw_exception(cls(stream.str().c_str(), cls::code, line, column, \
57 name)); \
58 } \
59 /**/
60 #endif // BOOST_NO_STRINGSTREAM
61 #endif // BOOST_WAVE_LEXER_THROW
62
63 #if !defined(BOOST_WAVE_LEXER_THROW_VAR)
64 #ifdef BOOST_NO_STRINGSTREAM
65 #include <strstream>
66 #define BOOST_WAVE_LEXER_THROW_VAR(cls, codearg, msg, line, column, name) \
67 { \
68 using namespace boost::wave; \
69 cls::error_code code = static_cast<cls::error_code>(codearg); \
70 std::strstream stream; \
71 stream << cls::severity_text(code) << ": " \
72 << cls::error_text(code); \
73 if ((msg)[0] != 0) stream << ": " << (msg); \
74 stream << std::ends; \
75 std::string throwmsg = stream.str(); stream.freeze(false); \
76 boost::throw_exception(cls(throwmsg.c_str(), code, line, column, \
77 name)); \
78 } \
79 /**/
80 #else
81 #include <sstream>
82 #define BOOST_WAVE_LEXER_THROW_VAR(cls, codearg, msg, line, column, name) \
83 { \
84 using namespace boost::wave; \
85 cls::error_code code = static_cast<cls::error_code>(codearg); \
86 std::stringstream stream; \
87 stream << cls::severity_text(code) << ": " \
88 << cls::error_text(code); \
89 if ((msg)[0] != 0) stream << ": " << (msg); \
90 stream << std::ends; \
91 boost::throw_exception(cls(stream.str().c_str(), code, line, column, \
92 name)); \
93 } \
94 /**/
95 #endif // BOOST_NO_STRINGSTREAM
96 #endif // BOOST_WAVE_LEXER_THROW
97
98 ///////////////////////////////////////////////////////////////////////////////
99 namespace boost {
100 namespace wave {
101 namespace cpplexer {
102
103 ///////////////////////////////////////////////////////////////////////////////
104 // exception severity
105 namespace util {
106
107 enum severity {
108 severity_remark = 0,
109 severity_warning,
110 severity_error,
111 severity_fatal
112 };
113
114 inline char const *
get_severity(severity level)115 get_severity(severity level)
116 {
117 static char const *severity_text[] =
118 {
119 "remark", // severity_remark
120 "warning", // severity_warning
121 "error", // severity_error
122 "fatal error" // severity_fatal
123 };
124 BOOST_ASSERT(severity_remark <= level && level <= severity_fatal);
125 return severity_text[level];
126 }
127 }
128
129 ///////////////////////////////////////////////////////////////////////////////
130 // cpplexer_exception, the base class for all specific C++ lexer exceptions
131 class BOOST_SYMBOL_VISIBLE cpplexer_exception
132 : public std::exception
133 {
134 public:
cpplexer_exception(std::size_t line_,std::size_t column_,char const * filename_)135 cpplexer_exception(std::size_t line_, std::size_t column_, char const *filename_) throw()
136 : line(line_), column(column_)
137 {
138 unsigned int off = 0;
139 while (off < sizeof(filename)-1 && *filename_)
140 filename[off++] = *filename_++;
141 filename[off] = 0;
142 }
~cpplexer_exception()143 ~cpplexer_exception() throw() {}
144
145 char const *what() const throw() BOOST_OVERRIDE = 0; // to be overloaded
146 virtual char const *description() const throw() = 0;
147 virtual int get_errorcode() const throw() = 0;
148 virtual int get_severity() const throw() = 0;
149 virtual bool is_recoverable() const throw() = 0;
150
line_no() const151 std::size_t line_no() const throw() { return line; }
column_no() const152 std::size_t column_no() const throw() { return column; }
file_name() const153 char const *file_name() const throw() { return filename; }
154
155 protected:
156 char filename[512];
157 std::size_t line;
158 std::size_t column;
159 };
160
161 ///////////////////////////////////////////////////////////////////////////////
162 // lexing_exception error
163 class BOOST_SYMBOL_VISIBLE lexing_exception :
164 public cpplexer_exception
165 {
166 public:
167 enum error_code {
168 unexpected_error = 0,
169 universal_char_invalid = 1,
170 universal_char_base_charset = 2,
171 universal_char_not_allowed = 3,
172 invalid_long_long_literal = 4,
173 generic_lexing_error = 5,
174 generic_lexing_warning = 6
175 };
176
lexing_exception(char const * what_,error_code code,std::size_t line_,std::size_t column_,char const * filename_)177 lexing_exception(char const *what_, error_code code, std::size_t line_,
178 std::size_t column_, char const *filename_) throw()
179 : cpplexer_exception(line_, column_, filename_),
180 level(severity_level(code)), code(code)
181 {
182 unsigned int off = 0;
183 while (off < sizeof(buffer)-1 && *what_)
184 buffer[off++] = *what_++;
185 buffer[off] = 0;
186 }
~lexing_exception()187 ~lexing_exception() throw() {}
188
what() const189 char const *what() const throw() BOOST_OVERRIDE
190 {
191 return "boost::wave::lexing_exception";
192 }
description() const193 char const *description() const throw() BOOST_OVERRIDE
194 {
195 return buffer;
196 }
get_severity() const197 int get_severity() const throw() BOOST_OVERRIDE
198 {
199 return level;
200 }
get_errorcode() const201 int get_errorcode() const throw() BOOST_OVERRIDE
202 {
203 return code;
204 }
is_recoverable() const205 bool is_recoverable() const throw() BOOST_OVERRIDE
206 {
207 switch (get_errorcode()) {
208 case lexing_exception::universal_char_invalid:
209 case lexing_exception::universal_char_base_charset:
210 case lexing_exception::universal_char_not_allowed:
211 case lexing_exception::invalid_long_long_literal:
212 case lexing_exception::generic_lexing_warning:
213 case lexing_exception::generic_lexing_error:
214 return true; // for now allow all exceptions to be recoverable
215
216 case lexing_exception::unexpected_error:
217 default:
218 break;
219 }
220 return false;
221 }
222
error_text(int code)223 static char const *error_text(int code)
224 {
225 // error texts in this array must appear in the same order as the items in
226 // the error enum above
227 static char const *preprocess_exception_errors[] = {
228 "unexpected error (should not happen)", // unexpected_error
229 "universal character name specifies an invalid character", // universal_char_invalid
230 "a universal character name cannot designate a character in the "
231 "basic character set", // universal_char_base_charset
232 "this universal character is not allowed in an identifier", // universal_char_not_allowed
233 "long long suffixes are not allowed in pure C++ mode, "
234 "enable long_long mode to allow these", // invalid_long_long_literal
235 "generic lexer error", // generic_lexing_error
236 "generic lexer warning" // generic_lexing_warning
237 };
238 return preprocess_exception_errors[code];
239 }
240
severity_level(int code)241 static util::severity severity_level(int code)
242 {
243 static util::severity preprocess_exception_severity[] = {
244 util::severity_fatal, // unexpected_error
245 util::severity_error, // universal_char_invalid
246 util::severity_error, // universal_char_base_charset
247 util::severity_error, // universal_char_not_allowed
248 util::severity_warning, // invalid_long_long_literal
249 util::severity_error, // generic_lexing_error
250 util::severity_warning // invalid_long_long_literal
251 };
252 return preprocess_exception_severity[code];
253 }
severity_text(int code)254 static char const *severity_text(int code)
255 {
256 return util::get_severity(severity_level(code));
257 }
258
259 private:
260 char buffer[512];
261 util::severity level;
262 error_code code;
263 };
264
265 ///////////////////////////////////////////////////////////////////////////////
266 //
267 // The is_recoverable() function allows to decide, whether it is possible
268 // simply to continue after a given exception was thrown by Wave.
269 //
270 // This is kind of a hack to allow to recover from certain errors as long as
271 // Wave doesn't provide better means of error recovery.
272 //
273 ///////////////////////////////////////////////////////////////////////////////
274 inline bool
is_recoverable(lexing_exception const & e)275 is_recoverable(lexing_exception const& e)
276 {
277 return e.is_recoverable();
278 }
279
280 ///////////////////////////////////////////////////////////////////////////////
281 } // namespace cpplexer
282 } // namespace wave
283 } // namespace boost
284
285 // the suffix header occurs after all of the code
286 #ifdef BOOST_HAS_ABI_HEADERS
287 #include BOOST_ABI_SUFFIX
288 #endif
289
290 #endif // !defined(BOOST_CPPLEXER_EXCEPTIONS_HPP_1A09DE1A_6D1F_4091_AF7F_5F13AB0D31AB_INCLUDED)
291