Line data Source code
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 0 : bool ccomment_has_newline(TokenT const& token) 37 : { 38 : using namespace boost::wave; 39 : 40 0 : if (T_CCOMMENT == token_id(token) && 41 0 : TokenT::string_type::npos != token.get_value().find_first_of("\n")) 42 : { 43 0 : 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 0 : int ccomment_count_newlines(TokenT const& token) 53 : { 54 : using namespace boost::wave; 55 0 : int newlines = 0; 56 0 : if (T_CCOMMENT == token_id(token)) { 57 0 : typename TokenT::string_type const& value = token.get_value(); 58 0 : typename TokenT::string_type::size_type p = value.find_first_of("\n"); 59 : 60 0 : while (TokenT::string_type::npos != p) { 61 0 : ++newlines; 62 0 : p = value.find_first_of("\n", p+1); 63 : } 64 : } 65 0 : 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 0 : int rawstring_count_newlines(TokenT const& token) 74 : { 75 : using namespace boost::wave; 76 0 : int newlines = 0; 77 0 : if (T_RAWSTRINGLIT == token_id(token)) { 78 0 : typename TokenT::string_type const& value = token.get_value(); 79 0 : typename TokenT::string_type::size_type p = value.find_first_of("\n"); 80 : 81 0 : while (TokenT::string_type::npos != p) { 82 0 : ++newlines; 83 0 : p = value.find_first_of("\n", p+1); 84 : } 85 : } 86 0 : 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 :