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