First public contribution.
1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
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 =============================================================================*/
13 #if !defined(WHITESPACE_HANDLING_HPP_INCLUDED)
14 #define WHITESPACE_HANDLING_HPP_INCLUDED
16 #include <boost/wave/wave_config.hpp>
17 #include <boost/wave/token_ids.hpp>
18 #include <boost/wave/preprocessing_hooks.hpp>
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
25 ///////////////////////////////////////////////////////////////////////////////
28 namespace context_policies {
31 ///////////////////////////////////////////////////////////////////////////
32 // This function returns true if the given C style comment contains at
34 template <typename TokenT>
35 bool ccomment_has_newline(TokenT const& token)
37 using namespace boost::wave;
39 if (T_CCOMMENT == token_id(token) &&
40 TokenT::string_type::npos != token.get_value().find_first_of("\n"))
47 ///////////////////////////////////////////////////////////////////////////
48 // This function returns the number of newlines in the given C style
50 template <typename TokenT>
51 int ccomment_count_newlines(TokenT const& token)
53 using namespace boost::wave;
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");
59 while (TokenT::string_type::npos != p) {
61 p = value.find_first_of("\n", p+1);
68 ///////////////////////////////////////////////////////////////////////////////
69 template <typename TokenT>
71 : public default_preprocessing_hooks
76 template <typename ContextT>
77 bool may_skip_whitespace(ContextT const& ctx, TokenT &token,
78 bool &skipped_newline);
81 bool skip_cppcomment(boost::wave::token_id id)
83 return !preserve_comments && T_CPPCOMMENT == id;
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;
93 template <typename TokenT>
95 eat_whitespace<TokenT>::eat_whitespace()
96 : state(&eat_whitespace::newline), preserve_comments(false)
100 template <typename TokenT>
101 template <typename ContextT>
103 eat_whitespace<TokenT>::may_skip_whitespace(ContextT const& ctx, TokenT &token,
104 bool &skipped_newline)
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);
111 template <typename TokenT>
113 eat_whitespace<TokenT>::general(TokenT &token, bool &skipped_newline)
115 using namespace boost::wave;
117 token_id id = token_id(token);
118 if (T_NEWLINE == id || T_CPPCOMMENT == id) {
119 state = &eat_whitespace::newline;
121 else if (T_SPACE == id || T_SPACE2 == id || T_CCOMMENT == id) {
122 state = &eat_whitespace::whitespace;
124 if (util::ccomment_has_newline(token))
125 skipped_newline = true;
127 if ((!preserve_comments || T_CCOMMENT != id) &&
128 token.get_value().size() > 1)
130 token.set_value(" "); // replace with a single space
134 state = &eat_whitespace::general;
139 template <typename TokenT>
141 eat_whitespace<TokenT>::newline(TokenT &token, bool &skipped_newline)
143 using namespace boost::wave;
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);
151 else if (T_SPACE != id && T_SPACE2 != id && T_CCOMMENT != id) {
152 return general(token, skipped_newline);
155 if (T_CCOMMENT == id) {
156 if (util::ccomment_has_newline(token)) {
157 skipped_newline = true;
158 state = &eat_whitespace::newline_2nd;
160 if (preserve_comments) {
161 state = &eat_whitespace::general;
169 template <typename TokenT>
171 eat_whitespace<TokenT>::newline_2nd(TokenT &token, bool &skipped_newline)
173 using namespace boost::wave;
175 token_id id = token_id(token);
176 if (T_SPACE == id || T_SPACE2 == id)
178 if (T_CCOMMENT == id) {
179 if (util::ccomment_has_newline(token))
180 skipped_newline = true;
182 if (preserve_comments) {
183 state = &eat_whitespace::general;
188 if (T_NEWLINE != id && T_CPPCOMMENT != id)
189 return general(token, skipped_newline);
191 skipped_newline = true;
192 return T_NEWLINE == id || skip_cppcomment(id);
195 template <typename TokenT>
197 eat_whitespace<TokenT>::whitespace(TokenT &token, bool &skipped_newline)
199 using namespace boost::wave;
201 token_id id = token_id(token);
202 if (T_SPACE != id && T_SPACE2 != id &&
203 T_CCOMMENT != id && T_CPPCOMMENT != id)
205 return general(token, skipped_newline);
208 if (T_CCOMMENT == id) {
209 if (util::ccomment_has_newline(token))
210 skipped_newline = true;
211 return !preserve_comments;
214 return T_SPACE == id || T_SPACE2 == id || skip_cppcomment(id);
217 ///////////////////////////////////////////////////////////////////////////////
218 } // namespace context_policies
222 // the suffix header occurs after all of the code
223 #ifdef BOOST_HAS_ABI_HEADERS
224 #include BOOST_ABI_SUFFIX
227 #endif // !defined(WHITESPACE_HANDLING_HPP_INCLUDED)