| 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-2007 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 |  | 
|---|
| 20 | // this must occur after all of the includes and before any code appears | 
|---|
| 21 | #ifdef BOOST_HAS_ABI_HEADERS | 
|---|
| 22 | #include BOOST_ABI_PREFIX | 
|---|
| 23 | #endif | 
|---|
| 24 |  | 
|---|
| 25 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 26 | namespace boost { | 
|---|
| 27 | namespace wave { | 
|---|
| 28 | namespace context_policies { | 
|---|
| 29 |  | 
|---|
| 30 | namespace util { | 
|---|
| 31 |     /////////////////////////////////////////////////////////////////////////// | 
|---|
| 32 |     //  This function returns true if the given C style comment contains at  | 
|---|
| 33 |     //  least one newline | 
|---|
| 34 |     template <typename TokenT> | 
|---|
| 35 |     bool ccomment_has_newline(TokenT const& token) | 
|---|
| 36 |     { | 
|---|
| 37 |         using namespace boost::wave; | 
|---|
| 38 |  | 
|---|
| 39 |         if (T_CCOMMENT == token_id(token) && | 
|---|
| 40 |             TokenT::string_type::npos != token.get_value().find_first_of("\n")) | 
|---|
| 41 |         { | 
|---|
| 42 |             return true; | 
|---|
| 43 |         } | 
|---|
| 44 |         return false; | 
|---|
| 45 |     } | 
|---|
| 46 |  | 
|---|
| 47 |     /////////////////////////////////////////////////////////////////////////// | 
|---|
| 48 |     //  This function returns the number of newlines in the given C style  | 
|---|
| 49 |     //  comment  | 
|---|
| 50 |     template <typename TokenT> | 
|---|
| 51 |     int ccomment_count_newlines(TokenT const& token) | 
|---|
| 52 |     { | 
|---|
| 53 |         using namespace boost::wave; | 
|---|
| 54 |         int newlines = 0; | 
|---|
| 55 |         if (T_CCOMMENT == token_id(token)) { | 
|---|
| 56 |         typename TokenT::string_type const& value = token.get_value(); | 
|---|
| 57 |         typename TokenT::string_type::size_type p = value.find_first_of("\n"); | 
|---|
| 58 |  | 
|---|
| 59 |             while (TokenT::string_type::npos != p) { | 
|---|
| 60 |                 ++newlines; | 
|---|
| 61 |                 p = value.find_first_of("\n", p+1); | 
|---|
| 62 |             }  | 
|---|
| 63 |         } | 
|---|
| 64 |         return newlines; | 
|---|
| 65 |     } | 
|---|
| 66 | } | 
|---|
| 67 |  | 
|---|
| 68 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 69 | template <typename TokenT> | 
|---|
| 70 | class eat_whitespace  | 
|---|
| 71 | :   public default_preprocessing_hooks | 
|---|
| 72 | { | 
|---|
| 73 | public: | 
|---|
| 74 |     eat_whitespace(); | 
|---|
| 75 |      | 
|---|
| 76 |     template <typename ContextT> | 
|---|
| 77 |     bool may_skip_whitespace(ContextT const& ctx, TokenT &token,  | 
|---|
| 78 |         bool &skipped_newline); | 
|---|
| 79 |  | 
|---|
| 80 | protected: | 
|---|
| 81 |     bool skip_cppcomment(boost::wave::token_id id) | 
|---|
| 82 |     { | 
|---|
| 83 |         return !preserve_comments && T_CPPCOMMENT == id; | 
|---|
| 84 |     } | 
|---|
| 85 |      | 
|---|
| 86 | private: | 
|---|
| 87 |     typedef bool state_t(TokenT &token, bool &skipped_newline); | 
|---|
| 88 |     state_t eat_whitespace::* state; | 
|---|
| 89 |     state_t general, newline, newline_2nd, whitespace; | 
|---|
| 90 |     bool preserve_comments; | 
|---|
| 91 | }; | 
|---|
| 92 |  | 
|---|
| 93 | template <typename TokenT> | 
|---|
| 94 | inline  | 
|---|
| 95 | eat_whitespace<TokenT>::eat_whitespace() | 
|---|
| 96 | :   state(&eat_whitespace::newline), preserve_comments(false) | 
|---|
| 97 | { | 
|---|
| 98 | } | 
|---|
| 99 |  | 
|---|
| 100 | template <typename TokenT> | 
|---|
| 101 | template <typename ContextT> | 
|---|
| 102 | inline bool  | 
|---|
| 103 | eat_whitespace<TokenT>::may_skip_whitespace(ContextT const& ctx, TokenT &token,  | 
|---|
| 104 |     bool &skipped_newline)  | 
|---|
| 105 | { | 
|---|
| 106 |     // re-initialize the preserve comments state | 
|---|
| 107 |     preserve_comments = boost::wave::need_preserve_comments(ctx.get_language()); | 
|---|
| 108 |     return (this->*state)(token, skipped_newline); | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | template <typename TokenT> | 
|---|
| 112 | inline bool  | 
|---|
| 113 | eat_whitespace<TokenT>::general(TokenT &token, bool &skipped_newline)  | 
|---|
| 114 | { | 
|---|
| 115 |     using namespace boost::wave; | 
|---|
| 116 |  | 
|---|
| 117 |     token_id id = token_id(token); | 
|---|
| 118 |     if (T_NEWLINE == id || T_CPPCOMMENT == id) { | 
|---|
| 119 |         state = &eat_whitespace::newline; | 
|---|
| 120 |     } | 
|---|
| 121 |     else if (T_SPACE == id || T_SPACE2 == id || T_CCOMMENT == id) { | 
|---|
| 122 |         state = &eat_whitespace::whitespace; | 
|---|
| 123 |  | 
|---|
| 124 |         if (util::ccomment_has_newline(token))  | 
|---|
| 125 |             skipped_newline = true; | 
|---|
| 126 |  | 
|---|
| 127 |         if ((!preserve_comments || T_CCOMMENT != id) &&  | 
|---|
| 128 |             token.get_value().size() > 1) | 
|---|
| 129 |         { | 
|---|
| 130 |             token.set_value(" ");   // replace with a single space | 
|---|
| 131 |         } | 
|---|
| 132 |     } | 
|---|
| 133 |     else { | 
|---|
| 134 |         state = &eat_whitespace::general; | 
|---|
| 135 |     } | 
|---|
| 136 |     return false; | 
|---|
| 137 | } | 
|---|
| 138 |  | 
|---|
| 139 | template <typename TokenT> | 
|---|
| 140 | inline bool  | 
|---|
| 141 | eat_whitespace<TokenT>::newline(TokenT &token, bool &skipped_newline)  | 
|---|
| 142 | { | 
|---|
| 143 |     using namespace boost::wave; | 
|---|
| 144 |      | 
|---|
| 145 |     token_id id = token_id(token); | 
|---|
| 146 |     if (T_NEWLINE == id || T_CPPCOMMENT == id) { | 
|---|
| 147 |         skipped_newline = true; | 
|---|
| 148 |         state = &eat_whitespace::newline_2nd; | 
|---|
| 149 |         return T_NEWLINE == id || skip_cppcomment(id); | 
|---|
| 150 |     } | 
|---|
| 151 |     else if (T_SPACE != id && T_SPACE2 != id && T_CCOMMENT != id) { | 
|---|
| 152 |         return general(token, skipped_newline); | 
|---|
| 153 |     } | 
|---|
| 154 |  | 
|---|
| 155 |     if (T_CCOMMENT == id) { | 
|---|
| 156 |         if (util::ccomment_has_newline(token)) { | 
|---|
| 157 |             skipped_newline = true; | 
|---|
| 158 |             state = &eat_whitespace::newline_2nd; | 
|---|
| 159 |         } | 
|---|
| 160 |         if (preserve_comments) { | 
|---|
| 161 |             state = &eat_whitespace::general; | 
|---|
| 162 |             return false; | 
|---|
| 163 |         } | 
|---|
| 164 |         // fall through... | 
|---|
| 165 |     } | 
|---|
| 166 |     return true; | 
|---|
| 167 | } | 
|---|
| 168 |  | 
|---|
| 169 | template <typename TokenT> | 
|---|
| 170 | inline bool  | 
|---|
| 171 | eat_whitespace<TokenT>::newline_2nd(TokenT &token, bool &skipped_newline)  | 
|---|
| 172 | { | 
|---|
| 173 |     using namespace boost::wave; | 
|---|
| 174 |      | 
|---|
| 175 |     token_id id = token_id(token); | 
|---|
| 176 |     if (T_SPACE == id || T_SPACE2 == id) | 
|---|
| 177 |         return true; | 
|---|
| 178 |     if (T_CCOMMENT == id) { | 
|---|
| 179 |         if (util::ccomment_has_newline(token)) | 
|---|
| 180 |             skipped_newline = true; | 
|---|
| 181 |  | 
|---|
| 182 |         if (preserve_comments) { | 
|---|
| 183 |             state = &eat_whitespace::general; | 
|---|
| 184 |             return false; | 
|---|
| 185 |         } | 
|---|
| 186 |         return  true; | 
|---|
| 187 |     } | 
|---|
| 188 |     if (T_NEWLINE != id && T_CPPCOMMENT != id)  | 
|---|
| 189 |         return general(token, skipped_newline); | 
|---|
| 190 |  | 
|---|
| 191 |     skipped_newline = true; | 
|---|
| 192 |     return T_NEWLINE == id || skip_cppcomment(id); | 
|---|
| 193 | } | 
|---|
| 194 |  | 
|---|
| 195 | template <typename TokenT> | 
|---|
| 196 | inline bool  | 
|---|
| 197 | eat_whitespace<TokenT>::whitespace(TokenT &token, bool &skipped_newline)  | 
|---|
| 198 | { | 
|---|
| 199 |     using namespace boost::wave; | 
|---|
| 200 |      | 
|---|
| 201 |     token_id id = token_id(token); | 
|---|
| 202 |     if (T_SPACE != id && T_SPACE2 != id &&  | 
|---|
| 203 |         T_CCOMMENT != id && T_CPPCOMMENT != id)  | 
|---|
| 204 |     { | 
|---|
| 205 |         return general(token, skipped_newline); | 
|---|
| 206 |     } | 
|---|
| 207 |      | 
|---|
| 208 |     if (T_CCOMMENT == id) { | 
|---|
| 209 |         if (util::ccomment_has_newline(token)) | 
|---|
| 210 |             skipped_newline = true; | 
|---|
| 211 |         return !preserve_comments; | 
|---|
| 212 |     } | 
|---|
| 213 |  | 
|---|
| 214 |     return T_SPACE == id || T_SPACE2 == id || skip_cppcomment(id); | 
|---|
| 215 | } | 
|---|
| 216 |  | 
|---|
| 217 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 218 | }   // namespace context_policies | 
|---|
| 219 | }   // namespace wave | 
|---|
| 220 | }   // namespace boost | 
|---|
| 221 |  | 
|---|
| 222 | // the suffix header occurs after all of the code | 
|---|
| 223 | #ifdef BOOST_HAS_ABI_HEADERS | 
|---|
| 224 | #include BOOST_ABI_SUFFIX | 
|---|
| 225 | #endif | 
|---|
| 226 |  | 
|---|
| 227 | #endif // !defined(WHITESPACE_HANDLING_HPP_INCLUDED) | 
|---|
| 228 |  | 
|---|