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