Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Boost.Wave: A Standard compliant C++ preprocessor library
|
Chris@16
|
3 Whitespace eater
|
Chris@16
|
4
|
Chris@16
|
5 http://www.boost.org/
|
Chris@16
|
6
|
Chris@16
|
7 Copyright (c) 2003 Paul Mensonides
|
Chris@16
|
8 Copyright (c) 2001-2012 Hartmut Kaiser.
|
Chris@16
|
9 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
10 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
11 =============================================================================*/
|
Chris@16
|
12
|
Chris@16
|
13 #if !defined(WHITESPACE_HANDLING_HPP_INCLUDED)
|
Chris@16
|
14 #define WHITESPACE_HANDLING_HPP_INCLUDED
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/wave/wave_config.hpp>
|
Chris@16
|
17 #include <boost/wave/token_ids.hpp>
|
Chris@16
|
18 #include <boost/wave/preprocessing_hooks.hpp>
|
Chris@16
|
19 #include <boost/wave/language_support.hpp>
|
Chris@16
|
20
|
Chris@16
|
21 // this must occur after all of the includes and before any code appears
|
Chris@16
|
22 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
23 #include BOOST_ABI_PREFIX
|
Chris@16
|
24 #endif
|
Chris@16
|
25
|
Chris@16
|
26 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
27 namespace boost {
|
Chris@16
|
28 namespace wave {
|
Chris@16
|
29 namespace context_policies {
|
Chris@16
|
30
|
Chris@16
|
31 namespace util {
|
Chris@16
|
32 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
33 // This function returns true if the given C style comment contains at
|
Chris@16
|
34 // least one newline
|
Chris@16
|
35 template <typename TokenT>
|
Chris@16
|
36 bool ccomment_has_newline(TokenT const& token)
|
Chris@16
|
37 {
|
Chris@16
|
38 using namespace boost::wave;
|
Chris@16
|
39
|
Chris@16
|
40 if (T_CCOMMENT == token_id(token) &&
|
Chris@16
|
41 TokenT::string_type::npos != token.get_value().find_first_of("\n"))
|
Chris@16
|
42 {
|
Chris@16
|
43 return true;
|
Chris@16
|
44 }
|
Chris@16
|
45 return false;
|
Chris@16
|
46 }
|
Chris@16
|
47
|
Chris@16
|
48 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
49 // This function returns the number of newlines in the given C style
|
Chris@16
|
50 // comment
|
Chris@16
|
51 template <typename TokenT>
|
Chris@16
|
52 int ccomment_count_newlines(TokenT const& token)
|
Chris@16
|
53 {
|
Chris@16
|
54 using namespace boost::wave;
|
Chris@16
|
55 int newlines = 0;
|
Chris@16
|
56 if (T_CCOMMENT == token_id(token)) {
|
Chris@16
|
57 typename TokenT::string_type const& value = token.get_value();
|
Chris@16
|
58 typename TokenT::string_type::size_type p = value.find_first_of("\n");
|
Chris@16
|
59
|
Chris@16
|
60 while (TokenT::string_type::npos != p) {
|
Chris@16
|
61 ++newlines;
|
Chris@16
|
62 p = value.find_first_of("\n", p+1);
|
Chris@16
|
63 }
|
Chris@16
|
64 }
|
Chris@16
|
65 return newlines;
|
Chris@16
|
66 }
|
Chris@16
|
67
|
Chris@16
|
68 #if BOOST_WAVE_SUPPORT_CPP0X != 0
|
Chris@16
|
69 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
70 // This function returns the number of newlines in the given C++11 style
|
Chris@16
|
71 // raw string
|
Chris@16
|
72 template <typename TokenT>
|
Chris@16
|
73 int rawstring_count_newlines(TokenT const& token)
|
Chris@16
|
74 {
|
Chris@16
|
75 using namespace boost::wave;
|
Chris@16
|
76 int newlines = 0;
|
Chris@16
|
77 if (T_RAWSTRINGLIT == token_id(token)) {
|
Chris@16
|
78 typename TokenT::string_type const& value = token.get_value();
|
Chris@16
|
79 typename TokenT::string_type::size_type p = value.find_first_of("\n");
|
Chris@16
|
80
|
Chris@16
|
81 while (TokenT::string_type::npos != p) {
|
Chris@16
|
82 ++newlines;
|
Chris@16
|
83 p = value.find_first_of("\n", p+1);
|
Chris@16
|
84 }
|
Chris@16
|
85 }
|
Chris@16
|
86 return newlines;
|
Chris@16
|
87 }
|
Chris@16
|
88 #endif
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
92 template <typename TokenT>
|
Chris@16
|
93 class eat_whitespace
|
Chris@16
|
94 : public default_preprocessing_hooks
|
Chris@16
|
95 {
|
Chris@16
|
96 public:
|
Chris@16
|
97 eat_whitespace();
|
Chris@16
|
98
|
Chris@16
|
99 template <typename ContextT>
|
Chris@16
|
100 bool may_skip_whitespace(ContextT const& ctx, TokenT &token,
|
Chris@16
|
101 bool &skipped_newline);
|
Chris@16
|
102 template <typename ContextT>
|
Chris@16
|
103 bool may_skip_whitespace(ContextT const& ctx, TokenT &token,
|
Chris@16
|
104 bool preserve_comments_, bool preserve_bol_whitespace_,
|
Chris@16
|
105 bool &skipped_newline);
|
Chris@16
|
106
|
Chris@16
|
107 protected:
|
Chris@16
|
108 bool skip_cppcomment(boost::wave::token_id id)
|
Chris@16
|
109 {
|
Chris@16
|
110 return !preserve_comments && T_CPPCOMMENT == id;
|
Chris@16
|
111 }
|
Chris@16
|
112
|
Chris@16
|
113 private:
|
Chris@16
|
114 typedef bool state_t(TokenT &token, bool &skipped_newline);
|
Chris@16
|
115 state_t eat_whitespace::* state;
|
Chris@16
|
116 state_t general, newline, newline_2nd, whitespace, bol_whitespace;
|
Chris@16
|
117 bool preserve_comments;
|
Chris@16
|
118 bool preserve_bol_whitespace;
|
Chris@16
|
119 };
|
Chris@16
|
120
|
Chris@16
|
121 template <typename TokenT>
|
Chris@16
|
122 inline
|
Chris@16
|
123 eat_whitespace<TokenT>::eat_whitespace()
|
Chris@16
|
124 : state(&eat_whitespace::newline), preserve_comments(false),
|
Chris@16
|
125 preserve_bol_whitespace(false)
|
Chris@16
|
126 {
|
Chris@16
|
127 }
|
Chris@16
|
128
|
Chris@16
|
129 template <typename TokenT>
|
Chris@16
|
130 template <typename ContextT>
|
Chris@16
|
131 inline bool
|
Chris@16
|
132 eat_whitespace<TokenT>::may_skip_whitespace(ContextT const& ctx, TokenT &token,
|
Chris@16
|
133 bool &skipped_newline)
|
Chris@16
|
134 {
|
Chris@16
|
135 // re-initialize the preserve comments state
|
Chris@16
|
136 preserve_comments = boost::wave::need_preserve_comments(ctx.get_language());
|
Chris@16
|
137 return (this->*state)(token, skipped_newline);
|
Chris@16
|
138 }
|
Chris@16
|
139
|
Chris@16
|
140 template <typename TokenT>
|
Chris@16
|
141 template <typename ContextT>
|
Chris@16
|
142 inline bool
|
Chris@16
|
143 eat_whitespace<TokenT>::may_skip_whitespace(ContextT const& ctx, TokenT &token,
|
Chris@16
|
144 bool preserve_comments_, bool preserve_bol_whitespace_,
|
Chris@16
|
145 bool &skipped_newline)
|
Chris@16
|
146 {
|
Chris@16
|
147 // re-initialize the preserve comments state
|
Chris@16
|
148 preserve_comments = preserve_comments_;
|
Chris@16
|
149 preserve_bol_whitespace = preserve_bol_whitespace_;
|
Chris@16
|
150 return (this->*state)(token, skipped_newline);
|
Chris@16
|
151 }
|
Chris@16
|
152
|
Chris@16
|
153 template <typename TokenT>
|
Chris@16
|
154 inline bool
|
Chris@16
|
155 eat_whitespace<TokenT>::general(TokenT &token, bool &skipped_newline)
|
Chris@16
|
156 {
|
Chris@16
|
157 using namespace boost::wave;
|
Chris@16
|
158
|
Chris@16
|
159 token_id id = token_id(token);
|
Chris@16
|
160 if (T_NEWLINE == id || T_CPPCOMMENT == id) {
|
Chris@16
|
161 state = &eat_whitespace::newline;
|
Chris@16
|
162 }
|
Chris@16
|
163 else if (T_SPACE == id || T_SPACE2 == id || T_CCOMMENT == id) {
|
Chris@16
|
164 state = &eat_whitespace::whitespace;
|
Chris@16
|
165
|
Chris@16
|
166 if (util::ccomment_has_newline(token))
|
Chris@16
|
167 skipped_newline = true;
|
Chris@16
|
168
|
Chris@16
|
169 if ((!preserve_comments || T_CCOMMENT != id) &&
|
Chris@16
|
170 token.get_value().size() > 1)
|
Chris@16
|
171 {
|
Chris@16
|
172 token.set_value(" "); // replace with a single space
|
Chris@16
|
173 }
|
Chris@16
|
174 }
|
Chris@16
|
175 else {
|
Chris@16
|
176 state = &eat_whitespace::general;
|
Chris@16
|
177 }
|
Chris@16
|
178 return false;
|
Chris@16
|
179 }
|
Chris@16
|
180
|
Chris@16
|
181 template <typename TokenT>
|
Chris@16
|
182 inline bool
|
Chris@16
|
183 eat_whitespace<TokenT>::newline(TokenT &token, bool &skipped_newline)
|
Chris@16
|
184 {
|
Chris@16
|
185 using namespace boost::wave;
|
Chris@16
|
186
|
Chris@16
|
187 token_id id = token_id(token);
|
Chris@16
|
188 if (T_NEWLINE == id || T_CPPCOMMENT == id) {
|
Chris@16
|
189 skipped_newline = true;
|
Chris@16
|
190 state = &eat_whitespace::newline_2nd;
|
Chris@16
|
191 return T_NEWLINE == id || skip_cppcomment(id);
|
Chris@16
|
192 }
|
Chris@16
|
193
|
Chris@16
|
194 if (T_SPACE != id && T_SPACE2 != id && T_CCOMMENT != id)
|
Chris@16
|
195 return general(token, skipped_newline);
|
Chris@16
|
196
|
Chris@16
|
197 if (T_CCOMMENT == id) {
|
Chris@16
|
198 if (util::ccomment_has_newline(token)) {
|
Chris@16
|
199 skipped_newline = true;
|
Chris@16
|
200 state = &eat_whitespace::newline_2nd;
|
Chris@16
|
201 }
|
Chris@16
|
202 if (preserve_comments) {
|
Chris@16
|
203 state = &eat_whitespace::general;
|
Chris@16
|
204 return false;
|
Chris@16
|
205 }
|
Chris@16
|
206 return true;
|
Chris@16
|
207 }
|
Chris@16
|
208
|
Chris@16
|
209 if (preserve_bol_whitespace) {
|
Chris@16
|
210 state = &eat_whitespace::bol_whitespace;
|
Chris@16
|
211 return false;
|
Chris@16
|
212 }
|
Chris@16
|
213
|
Chris@16
|
214 return true;
|
Chris@16
|
215 }
|
Chris@16
|
216
|
Chris@16
|
217 template <typename TokenT>
|
Chris@16
|
218 inline bool
|
Chris@16
|
219 eat_whitespace<TokenT>::newline_2nd(TokenT &token, bool &skipped_newline)
|
Chris@16
|
220 {
|
Chris@16
|
221 using namespace boost::wave;
|
Chris@16
|
222
|
Chris@16
|
223 token_id id = token_id(token);
|
Chris@16
|
224 if (T_SPACE == id || T_SPACE2 == id) {
|
Chris@16
|
225 if (preserve_bol_whitespace) {
|
Chris@16
|
226 state = &eat_whitespace::bol_whitespace;
|
Chris@16
|
227 return false;
|
Chris@16
|
228 }
|
Chris@16
|
229 return true;
|
Chris@16
|
230 }
|
Chris@16
|
231
|
Chris@16
|
232 if (T_CCOMMENT == id) {
|
Chris@16
|
233 if (util::ccomment_has_newline(token))
|
Chris@16
|
234 skipped_newline = true;
|
Chris@16
|
235
|
Chris@16
|
236 if (preserve_comments) {
|
Chris@16
|
237 state = &eat_whitespace::general;
|
Chris@16
|
238 return false;
|
Chris@16
|
239 }
|
Chris@16
|
240 return true;
|
Chris@16
|
241 }
|
Chris@16
|
242
|
Chris@16
|
243 if (T_NEWLINE != id && T_CPPCOMMENT != id)
|
Chris@16
|
244 return general(token, skipped_newline);
|
Chris@16
|
245
|
Chris@16
|
246 skipped_newline = true;
|
Chris@16
|
247 return T_NEWLINE == id || skip_cppcomment(id);
|
Chris@16
|
248 }
|
Chris@16
|
249
|
Chris@16
|
250 template <typename TokenT>
|
Chris@16
|
251 inline bool
|
Chris@16
|
252 eat_whitespace<TokenT>::bol_whitespace(TokenT &token, bool &skipped_newline)
|
Chris@16
|
253 {
|
Chris@16
|
254 using namespace boost::wave;
|
Chris@16
|
255
|
Chris@16
|
256 token_id id = token_id(token);
|
Chris@16
|
257 if (T_SPACE == id || T_SPACE2 == id)
|
Chris@16
|
258 return !preserve_bol_whitespace;
|
Chris@16
|
259
|
Chris@16
|
260 return general(token, skipped_newline);
|
Chris@16
|
261 }
|
Chris@16
|
262
|
Chris@16
|
263 template <typename TokenT>
|
Chris@16
|
264 inline bool
|
Chris@16
|
265 eat_whitespace<TokenT>::whitespace(TokenT &token, bool &skipped_newline)
|
Chris@16
|
266 {
|
Chris@16
|
267 using namespace boost::wave;
|
Chris@16
|
268
|
Chris@16
|
269 token_id id = token_id(token);
|
Chris@16
|
270 if (T_SPACE != id && T_SPACE2 != id &&
|
Chris@16
|
271 T_CCOMMENT != id && T_CPPCOMMENT != id)
|
Chris@16
|
272 {
|
Chris@16
|
273 return general(token, skipped_newline);
|
Chris@16
|
274 }
|
Chris@16
|
275
|
Chris@16
|
276 if (T_CCOMMENT == id) {
|
Chris@16
|
277 if (util::ccomment_has_newline(token))
|
Chris@16
|
278 skipped_newline = true;
|
Chris@16
|
279 return !preserve_comments;
|
Chris@16
|
280 }
|
Chris@16
|
281
|
Chris@16
|
282 return T_SPACE == id || T_SPACE2 == id || skip_cppcomment(id);
|
Chris@16
|
283 }
|
Chris@16
|
284
|
Chris@16
|
285 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
286 } // namespace context_policies
|
Chris@16
|
287 } // namespace wave
|
Chris@16
|
288 } // namespace boost
|
Chris@16
|
289
|
Chris@16
|
290 // the suffix header occurs after all of the code
|
Chris@16
|
291 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
292 #include BOOST_ABI_SUFFIX
|
Chris@16
|
293 #endif
|
Chris@16
|
294
|
Chris@16
|
295 #endif // !defined(WHITESPACE_HANDLING_HPP_INCLUDED)
|
Chris@16
|
296
|