]> git.sesse.net Git - casparcg/blob - dependencies/boost/boost/wave/whitespace_handling.hpp
Manually merged pull request #222
[casparcg] / dependencies / boost / boost / wave / whitespace_handling.hpp
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-2011 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++0x 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