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