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