1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
7 Copyright (c) 2003 Paul Mensonides
8 Copyright (c) 2001-2009 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>
19 #include <boost/wave/language_support.hpp>
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
26 ///////////////////////////////////////////////////////////////////////////////
29 namespace context_policies
{
32 ///////////////////////////////////////////////////////////////////////////
33 // This function returns true if the given C style comment contains at
35 template <typename TokenT
>
36 bool ccomment_has_newline(TokenT
const& token
)
38 using namespace boost::wave
;
40 if (T_CCOMMENT
== token_id(token
) &&
41 TokenT::string_type::npos
!= token
.get_value().find_first_of("\n"))
48 ///////////////////////////////////////////////////////////////////////////
49 // This function returns the number of newlines in the given C style
51 template <typename TokenT
>
52 int ccomment_count_newlines(TokenT
const& token
)
54 using namespace boost::wave
;
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");
60 while (TokenT::string_type::npos
!= p
) {
62 p
= value
.find_first_of("\n", p
+1);
69 ///////////////////////////////////////////////////////////////////////////////
70 template <typename TokenT
>
72 : public default_preprocessing_hooks
77 template <typename ContextT
>
78 bool may_skip_whitespace(ContextT
const& ctx
, TokenT
&token
,
79 bool &skipped_newline
);
82 bool skip_cppcomment(boost::wave::token_id id
)
84 return !preserve_comments
&& T_CPPCOMMENT
== id
;
88 typedef bool state_t(TokenT
&token
, bool &skipped_newline
);
89 state_t
eat_whitespace::* state
;
90 state_t general
, newline
, newline_2nd
, whitespace
;
91 bool preserve_comments
;
94 template <typename TokenT
>
96 eat_whitespace
<TokenT
>::eat_whitespace()
97 : state(&eat_whitespace::newline
), preserve_comments(false)
101 template <typename TokenT
>
102 template <typename ContextT
>
104 eat_whitespace
<TokenT
>::may_skip_whitespace(ContextT
const& ctx
, TokenT
&token
,
105 bool &skipped_newline
)
107 // re-initialize the preserve comments state
108 preserve_comments
= boost::wave::need_preserve_comments(ctx
.get_language());
109 return (this->*state
)(token
, skipped_newline
);
112 template <typename TokenT
>
114 eat_whitespace
<TokenT
>::general(TokenT
&token
, bool &skipped_newline
)
116 using namespace boost::wave
;
118 token_id id
= token_id(token
);
119 if (T_NEWLINE
== id
|| T_CPPCOMMENT
== id
) {
120 state
= &eat_whitespace::newline
;
122 else if (T_SPACE
== id
|| T_SPACE2
== id
|| T_CCOMMENT
== id
) {
123 state
= &eat_whitespace::whitespace
;
125 if (util::ccomment_has_newline(token
))
126 skipped_newline
= true;
128 if ((!preserve_comments
|| T_CCOMMENT
!= id
) &&
129 token
.get_value().size() > 1)
131 token
.set_value(" "); // replace with a single space
135 state
= &eat_whitespace::general
;
140 template <typename TokenT
>
142 eat_whitespace
<TokenT
>::newline(TokenT
&token
, bool &skipped_newline
)
144 using namespace boost::wave
;
146 token_id id
= token_id(token
);
147 if (T_NEWLINE
== id
|| T_CPPCOMMENT
== id
) {
148 skipped_newline
= true;
149 state
= &eat_whitespace::newline_2nd
;
150 return T_NEWLINE
== id
|| skip_cppcomment(id
);
152 else if (T_SPACE
!= id
&& T_SPACE2
!= id
&& T_CCOMMENT
!= id
) {
153 return general(token
, skipped_newline
);
156 if (T_CCOMMENT
== id
) {
157 if (util::ccomment_has_newline(token
)) {
158 skipped_newline
= true;
159 state
= &eat_whitespace::newline_2nd
;
161 if (preserve_comments
) {
162 state
= &eat_whitespace::general
;
170 template <typename TokenT
>
172 eat_whitespace
<TokenT
>::newline_2nd(TokenT
&token
, bool &skipped_newline
)
174 using namespace boost::wave
;
176 token_id id
= token_id(token
);
177 if (T_SPACE
== id
|| T_SPACE2
== id
)
179 if (T_CCOMMENT
== id
) {
180 if (util::ccomment_has_newline(token
))
181 skipped_newline
= true;
183 if (preserve_comments
) {
184 state
= &eat_whitespace::general
;
189 if (T_NEWLINE
!= id
&& T_CPPCOMMENT
!= id
)
190 return general(token
, skipped_newline
);
192 skipped_newline
= true;
193 return T_NEWLINE
== id
|| skip_cppcomment(id
);
196 template <typename TokenT
>
198 eat_whitespace
<TokenT
>::whitespace(TokenT
&token
, bool &skipped_newline
)
200 using namespace boost::wave
;
202 token_id id
= token_id(token
);
203 if (T_SPACE
!= id
&& T_SPACE2
!= id
&&
204 T_CCOMMENT
!= id
&& T_CPPCOMMENT
!= id
)
206 return general(token
, skipped_newline
);
209 if (T_CCOMMENT
== id
) {
210 if (util::ccomment_has_newline(token
))
211 skipped_newline
= true;
212 return !preserve_comments
;
215 return T_SPACE
== id
|| T_SPACE2
== id
|| skip_cppcomment(id
);
218 ///////////////////////////////////////////////////////////////////////////////
219 } // namespace context_policies
223 // the suffix header occurs after all of the code
224 #ifdef BOOST_HAS_ABI_HEADERS
225 #include BOOST_ABI_SUFFIX
228 #endif // !defined(WHITESPACE_HANDLING_HPP_INCLUDED)