]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/wave/cpplexer/cpp_lex_token.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / wave / cpplexer / cpp_lex_token.hpp
1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3
4 A generic C++ lexer token definition
5
6 http://www.boost.org/
7
8 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
9 Software License, Version 1.0. (See accompanying file
10 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 =============================================================================*/
12
13 #if !defined(BOOST_CPP_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED)
14 #define BOOST_CPP_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED
15
16 #include <boost/wave/wave_config.hpp>
17 #if BOOST_WAVE_SERIALIZATION != 0
18 #include <boost/serialization/serialization.hpp>
19 #endif
20 #include <boost/wave/util/file_position.hpp>
21 #include <boost/wave/token_ids.hpp>
22 #include <boost/wave/language_support.hpp>
23
24 #include <boost/throw_exception.hpp>
25 #include <boost/pool/singleton_pool.hpp>
26 #include <boost/detail/atomic_count.hpp>
27 #include <boost/optional.hpp>
28
29 // this must occur after all of the includes and before any code appears
30 #ifdef BOOST_HAS_ABI_HEADERS
31 #include BOOST_ABI_PREFIX
32 #endif
33
34 ///////////////////////////////////////////////////////////////////////////////
35 namespace boost {
36 namespace wave {
37 namespace cpplexer {
38
39 namespace impl {
40
41 template <typename StringTypeT, typename PositionT>
42 class token_data
43 {
44 public:
45 typedef StringTypeT string_type;
46 typedef PositionT position_type;
47
48 // default constructed tokens correspond to EOI tokens
49 token_data()
50 : id(T_EOI), refcnt(1)
51 {}
52
53 // construct an invalid token
54 explicit token_data(int)
55 : id(T_UNKNOWN), refcnt(1)
56 {}
57
58 token_data(token_id id_, string_type const &value_,
59 position_type const &pos_,
60 optional<position_type> const & expand_pos_ = boost::none)
61 : id(id_), value(value_), pos(pos_), expand_pos(expand_pos_), refcnt(1)
62 {}
63
64 token_data(token_data const& rhs)
65 : id(rhs.id), value(rhs.value), pos(rhs.pos), expand_pos(rhs.expand_pos), refcnt(1)
66 {}
67
68 ~token_data()
69 {}
70
71 std::size_t addref() { return ++refcnt; }
72 std::size_t release() { return --refcnt; }
73 std::size_t get_refcnt() const { return refcnt; }
74
75 // accessors
76 operator token_id() const { return id; }
77 string_type const &get_value() const { return value; }
78 position_type const &get_position() const { return pos; }
79 position_type const &get_expand_position() const
80 {
81 if (expand_pos)
82 return *expand_pos;
83 else
84 return pos;
85 }
86
87 void set_token_id (token_id id_) { id = id_; }
88 void set_value (string_type const &value_) { value = value_; }
89 void set_position (position_type const &pos_) { pos = pos_; }
90 void set_expand_position (position_type const & pos_) { expand_pos = pos_; }
91
92 friend bool operator== (token_data const& lhs, token_data const& rhs)
93 {
94 // two tokens are considered equal even if they refer to different
95 // positions
96 return (lhs.id == rhs.id && lhs.value == rhs.value) ? true : false;
97 }
98
99 void init(token_id id_, string_type const &value_, position_type const &pos_)
100 {
101 BOOST_ASSERT(refcnt == 1);
102 id = id_;
103 value = value_;
104 pos = pos_;
105 }
106
107 void init(token_data const& rhs)
108 {
109 BOOST_ASSERT(refcnt == 1);
110 id = rhs.id;
111 value = rhs.value;
112 pos = rhs.pos;
113 }
114
115 static void *operator new(std::size_t size);
116 static void operator delete(void *p, std::size_t size);
117
118 #if defined(BOOST_SPIRIT_DEBUG)
119 // debug support
120 void print (std::ostream &stream) const
121 {
122 stream << get_token_name(id) << "(";
123 for (std::size_t i = 0; i < value.size(); ++i) {
124 switch (value[i]) {
125 case '\r': stream << "\\r"; break;
126 case '\n': stream << "\\n"; break;
127 default:
128 stream << value[i];
129 break;
130 }
131 }
132 stream << ")";
133 }
134 #endif // defined(BOOST_SPIRIT_DEBUG)
135
136 #if BOOST_WAVE_SERIALIZATION != 0
137 friend class boost::serialization::access;
138 template<typename Archive>
139 void serialize(Archive &ar, const unsigned int version)
140 {
141 using namespace boost::serialization;
142 ar & make_nvp("id", id);
143 ar & make_nvp("value", value);
144 ar & make_nvp("position", pos);
145 }
146 #endif
147
148 private:
149 token_id id; // the token id
150 string_type value; // the text, which was parsed into this token
151 position_type pos; // the original file position
152 boost::optional<position_type> expand_pos; // where this token was expanded
153 boost::detail::atomic_count refcnt;
154 };
155
156 ///////////////////////////////////////////////////////////////////////////////
157 struct token_data_tag {};
158
159 template <typename StringTypeT, typename PositionT>
160 inline void *
161 token_data<StringTypeT, PositionT>::operator new(std::size_t size)
162 {
163 BOOST_ASSERT(sizeof(token_data<StringTypeT, PositionT>) == size);
164 typedef boost::singleton_pool<
165 token_data_tag, sizeof(token_data<StringTypeT, PositionT>)
166 > pool_type;
167
168 void *ret = pool_type::malloc();
169 if (0 == ret)
170 boost::throw_exception(std::bad_alloc());
171 return ret;
172 }
173
174 template <typename StringTypeT, typename PositionT>
175 inline void
176 token_data<StringTypeT, PositionT>::operator delete(void *p, std::size_t size)
177 {
178 BOOST_ASSERT(sizeof(token_data<StringTypeT, PositionT>) == size);
179 typedef boost::singleton_pool<
180 token_data_tag, sizeof(token_data<StringTypeT, PositionT>)
181 > pool_type;
182
183 if (0 != p)
184 pool_type::free(p);
185 }
186
187 } // namespace impl
188
189 ///////////////////////////////////////////////////////////////////////////////
190 // forward declaration of the token type
191 template <typename PositionT = boost::wave::util::file_position_type>
192 class lex_token;
193
194 ///////////////////////////////////////////////////////////////////////////////
195 //
196 // lex_token
197 //
198 ///////////////////////////////////////////////////////////////////////////////
199
200 template <typename PositionT>
201 class lex_token
202 {
203 public:
204 typedef BOOST_WAVE_STRINGTYPE string_type;
205 typedef PositionT position_type;
206
207 private:
208 typedef impl::token_data<string_type, position_type> data_type;
209
210 public:
211 // default constructed tokens correspond to EOI tokens
212 lex_token()
213 : data(0)
214 {}
215
216 // construct an invalid token
217 explicit lex_token(int)
218 : data(new data_type(0))
219 {}
220
221 lex_token(lex_token const& rhs)
222 : data(rhs.data)
223 {
224 if (0 != data)
225 data->addref();
226 }
227
228 lex_token(token_id id_, string_type const &value_, PositionT const &pos_)
229 : data(new data_type(id_, value_, pos_))
230 {}
231
232 ~lex_token()
233 {
234 if (0 != data && 0 == data->release())
235 delete data;
236 data = 0;
237 }
238
239 lex_token& operator=(lex_token const& rhs)
240 {
241 if (&rhs != this) {
242 if (0 != data && 0 == data->release())
243 delete data;
244
245 data = rhs.data;
246 if (0 != data)
247 data->addref();
248 }
249 return *this;
250 }
251
252 // accessors
253 operator token_id() const { return 0 != data ? token_id(*data) : T_EOI; }
254 string_type const &get_value() const { return data->get_value(); }
255 position_type const &get_position() const { return data->get_position(); }
256 position_type const &get_expand_position() const { return data->get_expand_position(); }
257 bool is_eoi() const { return 0 == data || token_id(*data) == T_EOI; }
258 bool is_valid() const { return 0 != data && token_id(*data) != T_UNKNOWN; }
259
260 void set_token_id (token_id id_) { make_unique(); data->set_token_id(id_); }
261 void set_value (string_type const &value_) { make_unique(); data->set_value(value_); }
262 void set_position (position_type const &pos_) { make_unique(); data->set_position(pos_); }
263 void set_expand_position (position_type const &pos_) { make_unique(); data->set_expand_position(pos_); }
264
265 friend bool operator== (lex_token const& lhs, lex_token const& rhs)
266 {
267 if (0 == rhs.data)
268 return 0 == lhs.data;
269 if (0 == lhs.data)
270 return false;
271 return *(lhs.data) == *(rhs.data);
272 }
273
274 // debug support
275 #if BOOST_WAVE_DUMP_PARSE_TREE != 0
276 // access functions for the tree_to_xml functionality
277 static int get_token_id(lex_token const &t)
278 { return token_id(t); }
279 static string_type get_token_value(lex_token const &t)
280 { return t.get_value(); }
281 #endif
282
283 #if defined(BOOST_SPIRIT_DEBUG)
284 // debug support
285 void print (std::ostream &stream) const
286 {
287 data->print(stream);
288 }
289 #endif // defined(BOOST_SPIRIT_DEBUG)
290
291 private:
292 #if BOOST_WAVE_SERIALIZATION != 0
293 friend class boost::serialization::access;
294 template<typename Archive>
295 void serialize(Archive &ar, const unsigned int version)
296 {
297 data->serialize(ar, version);
298 }
299 #endif
300
301 // make a unique copy of the current object
302 void make_unique()
303 {
304 if (1 == data->get_refcnt())
305 return;
306
307 data_type* newdata = new data_type(*data) ;
308
309 data->release(); // release this reference, can't get zero
310 data = newdata;
311 }
312
313 data_type* data;
314 };
315
316 ///////////////////////////////////////////////////////////////////////////////
317 // This overload is needed by the multi_pass/functor_input_policy to
318 // validate a token instance. It has to be defined in the same namespace
319 // as the token class itself to allow ADL to find it.
320 ///////////////////////////////////////////////////////////////////////////////
321 template <typename Position>
322 inline bool
323 token_is_valid(lex_token<Position> const& t)
324 {
325 return t.is_valid();
326 }
327
328 ///////////////////////////////////////////////////////////////////////////////
329 #if defined(BOOST_SPIRIT_DEBUG)
330 template <typename PositionT>
331 inline std::ostream &
332 operator<< (std::ostream &stream, lex_token<PositionT> const &object)
333 {
334 object.print(stream);
335 return stream;
336 }
337 #endif // defined(BOOST_SPIRIT_DEBUG)
338
339 ///////////////////////////////////////////////////////////////////////////////
340 } // namespace cpplexer
341 } // namespace wave
342 } // namespace boost
343
344 // the suffix header occurs after all of the code
345 #ifdef BOOST_HAS_ABI_HEADERS
346 #include BOOST_ABI_SUFFIX
347 #endif
348
349 #endif // !defined(BOOST_CPP_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED)