Chris@16
|
1 // Copyright (c) 2001-2011 Hartmut Kaiser
|
Chris@16
|
2 //
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #if !defined(BOOST_SPIRIT_LEX_TOKEN_FEB_10_2008_0751PM)
|
Chris@16
|
7 #define BOOST_SPIRIT_LEX_TOKEN_FEB_10_2008_0751PM
|
Chris@16
|
8
|
Chris@16
|
9 #if defined(_MSC_VER)
|
Chris@16
|
10 #pragma once
|
Chris@16
|
11 #endif
|
Chris@16
|
12
|
Chris@16
|
13 #include <boost/config.hpp>
|
Chris@16
|
14 #include <boost/detail/workaround.hpp>
|
Chris@16
|
15 #include <boost/spirit/home/qi/detail/assign_to.hpp>
|
Chris@16
|
16 #include <boost/spirit/home/support/attributes.hpp>
|
Chris@16
|
17 #include <boost/spirit/home/support/argument.hpp>
|
Chris@16
|
18 #include <boost/spirit/home/support/detail/lexer/generator.hpp>
|
Chris@16
|
19 #include <boost/spirit/home/support/detail/lexer/rules.hpp>
|
Chris@16
|
20 #include <boost/spirit/home/support/detail/lexer/consts.hpp>
|
Chris@16
|
21 #include <boost/spirit/home/support/utree/utree_traits_fwd.hpp>
|
Chris@16
|
22 #include <boost/spirit/home/lex/lexer/terminals.hpp>
|
Chris@16
|
23 #include <boost/fusion/include/vector.hpp>
|
Chris@16
|
24 #include <boost/fusion/include/at.hpp>
|
Chris@16
|
25 #include <boost/fusion/include/value_at.hpp>
|
Chris@16
|
26 #include <boost/detail/iterator.hpp>
|
Chris@16
|
27 #include <boost/variant.hpp>
|
Chris@16
|
28 #include <boost/mpl/bool.hpp>
|
Chris@16
|
29 #include <boost/mpl/vector.hpp>
|
Chris@16
|
30 #include <boost/mpl/is_sequence.hpp>
|
Chris@16
|
31 #include <boost/mpl/begin.hpp>
|
Chris@16
|
32 #include <boost/mpl/insert.hpp>
|
Chris@16
|
33 #include <boost/mpl/vector.hpp>
|
Chris@16
|
34 #include <boost/mpl/if.hpp>
|
Chris@16
|
35 #include <boost/mpl/or.hpp>
|
Chris@16
|
36 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
37 #include <boost/range/iterator_range.hpp>
|
Chris@16
|
38 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
Chris@16
|
39 #include <boost/static_assert.hpp>
|
Chris@16
|
40 #endif
|
Chris@16
|
41
|
Chris@16
|
42 #if defined(BOOST_SPIRIT_DEBUG)
|
Chris@16
|
43 #include <iosfwd>
|
Chris@16
|
44 #endif
|
Chris@16
|
45
|
Chris@16
|
46 namespace boost { namespace spirit { namespace lex { namespace lexertl
|
Chris@16
|
47 {
|
Chris@16
|
48 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
49 //
|
Chris@16
|
50 // The token is the type of the objects returned by default by the
|
Chris@16
|
51 // iterator.
|
Chris@16
|
52 //
|
Chris@16
|
53 // template parameters:
|
Chris@16
|
54 // Iterator The type of the iterator used to access the
|
Chris@16
|
55 // underlying character stream.
|
Chris@16
|
56 // AttributeTypes A mpl sequence containing the types of all
|
Chris@16
|
57 // required different token values to be supported
|
Chris@16
|
58 // by this token type.
|
Chris@16
|
59 // HasState A mpl::bool_ indicating, whether this token type
|
Chris@16
|
60 // should support lexer states.
|
Chris@16
|
61 // Idtype The type to use for the token id (defaults to
|
Chris@16
|
62 // std::size_t).
|
Chris@16
|
63 //
|
Chris@16
|
64 // It is possible to use other token types with the spirit::lex
|
Chris@16
|
65 // framework as well. If you plan to use a different type as your token
|
Chris@16
|
66 // type, you'll need to expose the following things from your token type
|
Chris@16
|
67 // to make it compatible with spirit::lex:
|
Chris@16
|
68 //
|
Chris@16
|
69 // typedefs
|
Chris@16
|
70 // iterator_type The type of the iterator used to access the
|
Chris@16
|
71 // underlying character stream.
|
Chris@16
|
72 //
|
Chris@16
|
73 // id_type The type of the token id used.
|
Chris@16
|
74 //
|
Chris@16
|
75 // methods
|
Chris@16
|
76 // default constructor
|
Chris@16
|
77 // This should initialize the token as an end of
|
Chris@16
|
78 // input token.
|
Chris@16
|
79 // constructors The prototype of the other required
|
Chris@16
|
80 // constructors should be:
|
Chris@16
|
81 //
|
Chris@16
|
82 // token(int)
|
Chris@16
|
83 // This constructor should initialize the token as
|
Chris@16
|
84 // an invalid token (not carrying any specific
|
Chris@16
|
85 // values)
|
Chris@16
|
86 //
|
Chris@16
|
87 // where: the int is used as a tag only and its value is
|
Chris@16
|
88 // ignored
|
Chris@16
|
89 //
|
Chris@16
|
90 // and:
|
Chris@16
|
91 //
|
Chris@16
|
92 // token(Idtype id, std::size_t state,
|
Chris@16
|
93 // iterator_type first, iterator_type last);
|
Chris@16
|
94 //
|
Chris@16
|
95 // where: id: token id
|
Chris@16
|
96 // state: lexer state this token was matched in
|
Chris@16
|
97 // first, last: pair of iterators marking the matched
|
Chris@16
|
98 // range in the underlying input stream
|
Chris@16
|
99 //
|
Chris@16
|
100 // accessors
|
Chris@16
|
101 // id() return the token id of the matched input sequence
|
Chris@16
|
102 // id(newid) set the token id of the token instance
|
Chris@16
|
103 //
|
Chris@16
|
104 // state() return the lexer state this token was matched in
|
Chris@16
|
105 //
|
Chris@16
|
106 // value() return the token value
|
Chris@16
|
107 //
|
Chris@16
|
108 // Additionally, you will have to implement a couple of helper functions
|
Chris@16
|
109 // in the same namespace as the token type: a comparison operator==() to
|
Chris@16
|
110 // compare your token instances, a token_is_valid() function and different
|
Chris@16
|
111 // specializations of the Spirit customization point
|
Chris@16
|
112 // assign_to_attribute_from_value as shown below.
|
Chris@16
|
113 //
|
Chris@16
|
114 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
115 template <typename Iterator = char const*
|
Chris@16
|
116 , typename AttributeTypes = mpl::vector0<>
|
Chris@16
|
117 , typename HasState = mpl::true_
|
Chris@16
|
118 , typename Idtype = std::size_t>
|
Chris@16
|
119 struct token;
|
Chris@16
|
120
|
Chris@16
|
121 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
122 // This specialization of the token type doesn't contain any item data and
|
Chris@16
|
123 // doesn't support working with lexer states.
|
Chris@16
|
124 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
125 template <typename Iterator, typename Idtype>
|
Chris@16
|
126 struct token<Iterator, lex::omit, mpl::false_, Idtype>
|
Chris@16
|
127 {
|
Chris@16
|
128 typedef Iterator iterator_type;
|
Chris@16
|
129 typedef mpl::false_ has_state;
|
Chris@16
|
130 typedef Idtype id_type;
|
Chris@16
|
131 typedef unused_type token_value_type;
|
Chris@16
|
132
|
Chris@16
|
133 // default constructed tokens correspond to EOI tokens
|
Chris@16
|
134 token() : id_(id_type(boost::lexer::npos)) {}
|
Chris@16
|
135
|
Chris@16
|
136 // construct an invalid token
|
Chris@16
|
137 explicit token(int) : id_(id_type(0)) {}
|
Chris@16
|
138
|
Chris@16
|
139 token(id_type id, std::size_t) : id_(id) {}
|
Chris@16
|
140
|
Chris@16
|
141 token(id_type id, std::size_t, token_value_type)
|
Chris@16
|
142 : id_(id) {}
|
Chris@16
|
143
|
Chris@16
|
144 token_value_type& value() { static token_value_type u; return u; }
|
Chris@16
|
145 token_value_type const& value() const { return unused; }
|
Chris@16
|
146
|
Chris@16
|
147 #if defined(BOOST_SPIRIT_DEBUG)
|
Chris@16
|
148 token(id_type id, std::size_t, Iterator const& first
|
Chris@16
|
149 , Iterator const& last)
|
Chris@16
|
150 : matched_(first, last)
|
Chris@16
|
151 , id_(id) {}
|
Chris@16
|
152 #else
|
Chris@16
|
153 token(id_type id, std::size_t, Iterator const&, Iterator const&)
|
Chris@16
|
154 : id_(id) {}
|
Chris@16
|
155 #endif
|
Chris@16
|
156
|
Chris@16
|
157 // this default conversion operator is needed to allow the direct
|
Chris@16
|
158 // usage of tokens in conjunction with the primitive parsers defined
|
Chris@16
|
159 // in Qi
|
Chris@16
|
160 operator id_type() const { return id_; }
|
Chris@16
|
161
|
Chris@16
|
162 // Retrieve or set the token id of this token instance.
|
Chris@16
|
163 id_type id() const { return id_; }
|
Chris@16
|
164 void id(id_type newid) { id_ = newid; }
|
Chris@16
|
165
|
Chris@16
|
166 std::size_t state() const { return 0; } // always '0' (INITIAL state)
|
Chris@16
|
167
|
Chris@16
|
168 bool is_valid() const
|
Chris@16
|
169 {
|
Chris@16
|
170 return 0 != id_ && id_type(boost::lexer::npos) != id_;
|
Chris@16
|
171 }
|
Chris@16
|
172
|
Chris@16
|
173 #if defined(BOOST_SPIRIT_DEBUG)
|
Chris@16
|
174 #if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
|
Chris@16
|
175 // workaround for MSVC10 which has problems copying a default
|
Chris@16
|
176 // constructed iterator_range
|
Chris@16
|
177 token& operator= (token const& rhs)
|
Chris@16
|
178 {
|
Chris@16
|
179 if (this != &rhs)
|
Chris@16
|
180 {
|
Chris@16
|
181 id_ = rhs.id_;
|
Chris@16
|
182 if (is_valid())
|
Chris@16
|
183 matched_ = rhs.matched_;
|
Chris@16
|
184 }
|
Chris@16
|
185 return *this;
|
Chris@16
|
186 }
|
Chris@16
|
187 #endif
|
Chris@16
|
188 std::pair<Iterator, Iterator> matched_;
|
Chris@16
|
189 #endif
|
Chris@16
|
190
|
Chris@16
|
191 protected:
|
Chris@16
|
192 id_type id_; // token id, 0 if nothing has been matched
|
Chris@16
|
193 };
|
Chris@16
|
194
|
Chris@16
|
195 #if defined(BOOST_SPIRIT_DEBUG)
|
Chris@16
|
196 template <typename Char, typename Traits, typename Iterator
|
Chris@16
|
197 , typename AttributeTypes, typename HasState, typename Idtype>
|
Chris@16
|
198 inline std::basic_ostream<Char, Traits>&
|
Chris@16
|
199 operator<< (std::basic_ostream<Char, Traits>& os
|
Chris@16
|
200 , token<Iterator, AttributeTypes, HasState, Idtype> const& t)
|
Chris@16
|
201 {
|
Chris@16
|
202 if (t.is_valid()) {
|
Chris@16
|
203 Iterator end = t.matched_.second;
|
Chris@16
|
204 for (Iterator it = t.matched_.first; it != end; ++it)
|
Chris@16
|
205 os << *it;
|
Chris@16
|
206 }
|
Chris@16
|
207 else {
|
Chris@16
|
208 os << "<invalid token>";
|
Chris@16
|
209 }
|
Chris@16
|
210 return os;
|
Chris@16
|
211 }
|
Chris@16
|
212 #endif
|
Chris@16
|
213
|
Chris@16
|
214 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
215 // This specialization of the token type doesn't contain any item data but
|
Chris@16
|
216 // supports working with lexer states.
|
Chris@16
|
217 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
218 template <typename Iterator, typename Idtype>
|
Chris@16
|
219 struct token<Iterator, lex::omit, mpl::true_, Idtype>
|
Chris@16
|
220 : token<Iterator, lex::omit, mpl::false_, Idtype>
|
Chris@16
|
221 {
|
Chris@16
|
222 private:
|
Chris@16
|
223 typedef token<Iterator, lex::omit, mpl::false_, Idtype> base_type;
|
Chris@16
|
224
|
Chris@16
|
225 public:
|
Chris@16
|
226 typedef typename base_type::id_type id_type;
|
Chris@16
|
227 typedef Iterator iterator_type;
|
Chris@16
|
228 typedef mpl::true_ has_state;
|
Chris@16
|
229 typedef unused_type token_value_type;
|
Chris@16
|
230
|
Chris@16
|
231 // default constructed tokens correspond to EOI tokens
|
Chris@16
|
232 token() : state_(boost::lexer::npos) {}
|
Chris@16
|
233
|
Chris@16
|
234 // construct an invalid token
|
Chris@16
|
235 explicit token(int) : base_type(0), state_(boost::lexer::npos) {}
|
Chris@16
|
236
|
Chris@16
|
237 token(id_type id, std::size_t state)
|
Chris@16
|
238 : base_type(id, boost::lexer::npos), state_(state) {}
|
Chris@16
|
239
|
Chris@16
|
240 token(id_type id, std::size_t state, token_value_type)
|
Chris@16
|
241 : base_type(id, boost::lexer::npos, unused)
|
Chris@16
|
242 , state_(state) {}
|
Chris@16
|
243
|
Chris@16
|
244 token(id_type id, std::size_t state
|
Chris@16
|
245 , Iterator const& first, Iterator const& last)
|
Chris@16
|
246 : base_type(id, boost::lexer::npos, first, last)
|
Chris@16
|
247 , state_(state) {}
|
Chris@16
|
248
|
Chris@16
|
249 std::size_t state() const { return state_; }
|
Chris@16
|
250
|
Chris@16
|
251 #if defined(BOOST_SPIRIT_DEBUG) && BOOST_WORKAROUND(BOOST_MSVC, == 1600)
|
Chris@16
|
252 // workaround for MSVC10 which has problems copying a default
|
Chris@16
|
253 // constructed iterator_range
|
Chris@16
|
254 token& operator= (token const& rhs)
|
Chris@16
|
255 {
|
Chris@16
|
256 if (this != &rhs)
|
Chris@16
|
257 {
|
Chris@16
|
258 this->base_type::operator=(static_cast<base_type const&>(rhs));
|
Chris@16
|
259 state_ = rhs.state_;
|
Chris@16
|
260 }
|
Chris@16
|
261 return *this;
|
Chris@16
|
262 }
|
Chris@16
|
263 #endif
|
Chris@16
|
264
|
Chris@16
|
265 protected:
|
Chris@16
|
266 std::size_t state_; // lexer state this token was matched in
|
Chris@16
|
267 };
|
Chris@16
|
268
|
Chris@16
|
269 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
270 // The generic version of the token type derives from the
|
Chris@16
|
271 // specialization above and adds a single data member holding the item
|
Chris@16
|
272 // data carried by the token instance.
|
Chris@16
|
273 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
274 namespace detail
|
Chris@16
|
275 {
|
Chris@16
|
276 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
277 // Meta-function to calculate the type of the variant data item to be
|
Chris@16
|
278 // stored with each token instance.
|
Chris@16
|
279 //
|
Chris@16
|
280 // Note: The iterator pair needs to be the first type in the list of
|
Chris@16
|
281 // types supported by the generated variant type (this is being
|
Chris@16
|
282 // used to identify whether the stored data item in a particular
|
Chris@16
|
283 // token instance needs to be converted from the pair of
|
Chris@16
|
284 // iterators (see the first of the assign_to_attribute_from_value
|
Chris@16
|
285 // specializations below).
|
Chris@16
|
286 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
287 template <typename IteratorPair, typename AttributeTypes>
|
Chris@16
|
288 struct token_value_typesequence
|
Chris@16
|
289 {
|
Chris@16
|
290 typedef typename mpl::insert<
|
Chris@16
|
291 AttributeTypes
|
Chris@16
|
292 , typename mpl::begin<AttributeTypes>::type
|
Chris@16
|
293 , IteratorPair
|
Chris@16
|
294 >::type sequence_type;
|
Chris@16
|
295 typedef typename make_variant_over<sequence_type>::type type;
|
Chris@16
|
296 };
|
Chris@16
|
297
|
Chris@16
|
298 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
299 // The type of the data item stored with a token instance is defined
|
Chris@16
|
300 // by the template parameter 'AttributeTypes' and may be:
|
Chris@16
|
301 //
|
Chris@16
|
302 // lex::omit: no data item is stored with the token
|
Chris@16
|
303 // instance (this is handled by the
|
Chris@16
|
304 // specializations of the token class
|
Chris@16
|
305 // below)
|
Chris@16
|
306 // mpl::vector0<>: each token instance stores a pair of
|
Chris@16
|
307 // iterators pointing to the matched input
|
Chris@16
|
308 // sequence
|
Chris@16
|
309 // mpl::vector<...>: each token instance stores a variant being
|
Chris@16
|
310 // able to store the pair of iterators pointing
|
Chris@16
|
311 // to the matched input sequence, or any of the
|
Chris@16
|
312 // types a specified in the mpl::vector<>
|
Chris@16
|
313 //
|
Chris@16
|
314 // All this is done to ensure the token type is as small (in terms
|
Chris@16
|
315 // of its byte-size) as possible.
|
Chris@16
|
316 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
317 template <typename IteratorPair, typename AttributeTypes>
|
Chris@16
|
318 struct token_value_type
|
Chris@16
|
319 : mpl::eval_if<
|
Chris@16
|
320 mpl::or_<
|
Chris@16
|
321 is_same<AttributeTypes, mpl::vector0<> >
|
Chris@16
|
322 , is_same<AttributeTypes, mpl::vector<> > >
|
Chris@16
|
323 , mpl::identity<IteratorPair>
|
Chris@16
|
324 , token_value_typesequence<IteratorPair, AttributeTypes> >
|
Chris@16
|
325 {};
|
Chris@16
|
326 }
|
Chris@16
|
327
|
Chris@16
|
328 template <typename Iterator, typename AttributeTypes, typename HasState
|
Chris@16
|
329 , typename Idtype>
|
Chris@16
|
330 struct token : token<Iterator, lex::omit, HasState, Idtype>
|
Chris@16
|
331 {
|
Chris@16
|
332 private: // precondition assertions
|
Chris@16
|
333 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
Chris@16
|
334 BOOST_STATIC_ASSERT((mpl::is_sequence<AttributeTypes>::value ||
|
Chris@16
|
335 is_same<AttributeTypes, lex::omit>::value));
|
Chris@16
|
336 #endif
|
Chris@16
|
337 typedef token<Iterator, lex::omit, HasState, Idtype> base_type;
|
Chris@16
|
338
|
Chris@16
|
339 protected:
|
Chris@16
|
340 // If no additional token value types are given, the the token will
|
Chris@16
|
341 // hold the plain pair of iterators pointing to the matched range
|
Chris@16
|
342 // in the underlying input sequence. Otherwise the token value is
|
Chris@16
|
343 // stored as a variant and will again hold the pair of iterators but
|
Chris@16
|
344 // is able to hold any of the given data types as well. The conversion
|
Chris@16
|
345 // from the iterator pair to the required data type is done when it is
|
Chris@16
|
346 // accessed for the first time.
|
Chris@16
|
347 typedef iterator_range<Iterator> iterpair_type;
|
Chris@16
|
348
|
Chris@16
|
349 public:
|
Chris@16
|
350 typedef typename base_type::id_type id_type;
|
Chris@16
|
351 typedef typename detail::token_value_type<
|
Chris@16
|
352 iterpair_type, AttributeTypes
|
Chris@16
|
353 >::type token_value_type;
|
Chris@16
|
354
|
Chris@16
|
355 typedef Iterator iterator_type;
|
Chris@16
|
356
|
Chris@16
|
357 // default constructed tokens correspond to EOI tokens
|
Chris@16
|
358 token() : value_(iterpair_type(iterator_type(), iterator_type())) {}
|
Chris@16
|
359
|
Chris@16
|
360 // construct an invalid token
|
Chris@16
|
361 explicit token(int)
|
Chris@16
|
362 : base_type(0)
|
Chris@16
|
363 , value_(iterpair_type(iterator_type(), iterator_type())) {}
|
Chris@16
|
364
|
Chris@16
|
365 token(id_type id, std::size_t state, token_value_type const& value)
|
Chris@16
|
366 : base_type(id, state, value)
|
Chris@16
|
367 , value_(value) {}
|
Chris@16
|
368
|
Chris@16
|
369 token(id_type id, std::size_t state, Iterator const& first
|
Chris@16
|
370 , Iterator const& last)
|
Chris@16
|
371 : base_type(id, state, first, last)
|
Chris@16
|
372 , value_(iterpair_type(first, last)) {}
|
Chris@16
|
373
|
Chris@16
|
374 token_value_type& value() { return value_; }
|
Chris@16
|
375 token_value_type const& value() const { return value_; }
|
Chris@16
|
376
|
Chris@16
|
377 #if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
|
Chris@16
|
378 // workaround for MSVC10 which has problems copying a default
|
Chris@16
|
379 // constructed iterator_range
|
Chris@16
|
380 token& operator= (token const& rhs)
|
Chris@16
|
381 {
|
Chris@16
|
382 if (this != &rhs)
|
Chris@16
|
383 {
|
Chris@16
|
384 this->base_type::operator=(static_cast<base_type const&>(rhs));
|
Chris@16
|
385 if (this->is_valid())
|
Chris@16
|
386 value_ = rhs.value_;
|
Chris@16
|
387 }
|
Chris@16
|
388 return *this;
|
Chris@16
|
389 }
|
Chris@16
|
390 #endif
|
Chris@16
|
391
|
Chris@16
|
392 protected:
|
Chris@16
|
393 token_value_type value_; // token value, by default a pair of iterators
|
Chris@16
|
394 };
|
Chris@16
|
395
|
Chris@16
|
396 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
397 // tokens are considered equal, if their id's match (these are unique)
|
Chris@16
|
398 template <typename Iterator, typename AttributeTypes, typename HasState
|
Chris@16
|
399 , typename Idtype>
|
Chris@16
|
400 inline bool
|
Chris@16
|
401 operator== (token<Iterator, AttributeTypes, HasState, Idtype> const& lhs,
|
Chris@16
|
402 token<Iterator, AttributeTypes, HasState, Idtype> const& rhs)
|
Chris@16
|
403 {
|
Chris@16
|
404 return lhs.id() == rhs.id();
|
Chris@16
|
405 }
|
Chris@16
|
406
|
Chris@16
|
407 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
408 // This overload is needed by the multi_pass/functor_input_policy to
|
Chris@16
|
409 // validate a token instance. It has to be defined in the same namespace
|
Chris@16
|
410 // as the token class itself to allow ADL to find it.
|
Chris@16
|
411 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
412 template <typename Iterator, typename AttributeTypes, typename HasState
|
Chris@16
|
413 , typename Idtype>
|
Chris@16
|
414 inline bool
|
Chris@16
|
415 token_is_valid(token<Iterator, AttributeTypes, HasState, Idtype> const& t)
|
Chris@16
|
416 {
|
Chris@16
|
417 return t.is_valid();
|
Chris@16
|
418 }
|
Chris@16
|
419 }}}}
|
Chris@16
|
420
|
Chris@16
|
421 namespace boost { namespace spirit { namespace traits
|
Chris@16
|
422 {
|
Chris@16
|
423 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
424 // We have to provide specializations for the customization point
|
Chris@16
|
425 // assign_to_attribute_from_value allowing to extract the needed value
|
Chris@16
|
426 // from the token.
|
Chris@16
|
427 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
428
|
Chris@16
|
429 // This is called from the parse function of token_def if the token_def
|
Chris@16
|
430 // has been defined to carry a special attribute type
|
Chris@16
|
431 template <typename Attribute, typename Iterator, typename AttributeTypes
|
Chris@16
|
432 , typename HasState, typename Idtype>
|
Chris@16
|
433 struct assign_to_attribute_from_value<Attribute
|
Chris@16
|
434 , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
Chris@16
|
435 {
|
Chris@16
|
436 static void
|
Chris@16
|
437 call(lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> const& t
|
Chris@16
|
438 , Attribute& attr)
|
Chris@16
|
439 {
|
Chris@16
|
440 // The goal of this function is to avoid the conversion of the pair of
|
Chris@16
|
441 // iterators (to the matched character sequence) into the token value
|
Chris@16
|
442 // of the required type being done more than once. For this purpose it
|
Chris@16
|
443 // checks whether the stored value type is still the default one (pair
|
Chris@16
|
444 // of iterators) and if yes, replaces the pair of iterators with the
|
Chris@16
|
445 // converted value to be returned from subsequent calls.
|
Chris@16
|
446
|
Chris@16
|
447 if (0 == t.value().which()) {
|
Chris@16
|
448 // first access to the token value
|
Chris@16
|
449 typedef iterator_range<Iterator> iterpair_type;
|
Chris@16
|
450 iterpair_type const& ip = boost::get<iterpair_type>(t.value());
|
Chris@16
|
451
|
Chris@16
|
452 // Interestingly enough we use the assign_to() framework defined in
|
Chris@16
|
453 // Spirit.Qi allowing to convert the pair of iterators to almost any
|
Chris@16
|
454 // required type (assign_to(), if available, uses the standard Spirit
|
Chris@16
|
455 // parsers to do the conversion).
|
Chris@16
|
456 spirit::traits::assign_to(ip.begin(), ip.end(), attr);
|
Chris@16
|
457
|
Chris@16
|
458 // If you get an error during the compilation of the following
|
Chris@16
|
459 // assignment expression, you probably forgot to list one or more
|
Chris@16
|
460 // types used as token value types (in your token_def<...>
|
Chris@16
|
461 // definitions) in your definition of the token class. I.e. any token
|
Chris@16
|
462 // value type used for a token_def<...> definition has to be listed
|
Chris@16
|
463 // during the declaration of the token type to use. For instance let's
|
Chris@16
|
464 // assume we have two token_def's:
|
Chris@16
|
465 //
|
Chris@16
|
466 // token_def<int> number; number = "...";
|
Chris@16
|
467 // token_def<std::string> identifier; identifier = "...";
|
Chris@16
|
468 //
|
Chris@16
|
469 // Then you'll have to use the following token type definition
|
Chris@16
|
470 // (assuming you are using the token class):
|
Chris@16
|
471 //
|
Chris@16
|
472 // typedef mpl::vector<int, std::string> token_values;
|
Chris@16
|
473 // typedef token<base_iter_type, token_values> token_type;
|
Chris@16
|
474 //
|
Chris@16
|
475 // where: base_iter_type is the iterator type used to expose the
|
Chris@16
|
476 // underlying input stream.
|
Chris@16
|
477 //
|
Chris@16
|
478 // This token_type has to be used as the second template parameter
|
Chris@16
|
479 // to the lexer class:
|
Chris@16
|
480 //
|
Chris@16
|
481 // typedef lexer<base_iter_type, token_type> lexer_type;
|
Chris@16
|
482 //
|
Chris@16
|
483 // again, assuming you're using the lexer<> template for your
|
Chris@16
|
484 // tokenization.
|
Chris@16
|
485
|
Chris@16
|
486 typedef lex::lexertl::token<
|
Chris@16
|
487 Iterator, AttributeTypes, HasState, Idtype> token_type;
|
Chris@16
|
488 spirit::traits::assign_to(
|
Chris@16
|
489 attr, const_cast<token_type&>(t).value()); // re-assign value
|
Chris@16
|
490 }
|
Chris@16
|
491 else {
|
Chris@16
|
492 // reuse the already assigned value
|
Chris@16
|
493 spirit::traits::assign_to(boost::get<Attribute>(t.value()), attr);
|
Chris@16
|
494 }
|
Chris@16
|
495 }
|
Chris@16
|
496 };
|
Chris@16
|
497
|
Chris@16
|
498 template <typename Attribute, typename Iterator, typename AttributeTypes
|
Chris@16
|
499 , typename HasState, typename Idtype>
|
Chris@16
|
500 struct assign_to_container_from_value<Attribute
|
Chris@16
|
501 , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
Chris@16
|
502 : assign_to_attribute_from_value<Attribute
|
Chris@16
|
503 , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
Chris@16
|
504 {};
|
Chris@16
|
505
|
Chris@16
|
506 template <typename Iterator, typename AttributeTypes
|
Chris@16
|
507 , typename HasState, typename Idtype>
|
Chris@16
|
508 struct assign_to_container_from_value<utree
|
Chris@16
|
509 , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
Chris@16
|
510 : assign_to_attribute_from_value<utree
|
Chris@16
|
511 , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
Chris@16
|
512 {};
|
Chris@16
|
513
|
Chris@16
|
514 template <typename Iterator>
|
Chris@16
|
515 struct assign_to_container_from_value<
|
Chris@16
|
516 iterator_range<Iterator>, iterator_range<Iterator> >
|
Chris@16
|
517 {
|
Chris@16
|
518 static void
|
Chris@16
|
519 call(iterator_range<Iterator> const& val, iterator_range<Iterator>& attr)
|
Chris@16
|
520 {
|
Chris@16
|
521 attr = val;
|
Chris@16
|
522 }
|
Chris@16
|
523 };
|
Chris@16
|
524
|
Chris@16
|
525 // These are called from the parse function of token_def if the token type
|
Chris@16
|
526 // has no special attribute type assigned
|
Chris@16
|
527 template <typename Attribute, typename Iterator, typename HasState
|
Chris@16
|
528 , typename Idtype>
|
Chris@16
|
529 struct assign_to_attribute_from_value<Attribute
|
Chris@16
|
530 , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> >
|
Chris@16
|
531 {
|
Chris@16
|
532 static void
|
Chris@16
|
533 call(lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> const& t
|
Chris@16
|
534 , Attribute& attr)
|
Chris@16
|
535 {
|
Chris@16
|
536 // The default type returned by the token_def parser component (if
|
Chris@16
|
537 // it has no token value type assigned) is the pair of iterators
|
Chris@16
|
538 // to the matched character sequence.
|
Chris@16
|
539 spirit::traits::assign_to(t.value().begin(), t.value().end(), attr);
|
Chris@16
|
540 }
|
Chris@16
|
541 };
|
Chris@16
|
542
|
Chris@16
|
543 // template <typename Attribute, typename Iterator, typename HasState
|
Chris@16
|
544 // , typename Idtype>
|
Chris@16
|
545 // struct assign_to_container_from_value<Attribute
|
Chris@16
|
546 // , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> >
|
Chris@16
|
547 // : assign_to_attribute_from_value<Attribute
|
Chris@16
|
548 // , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> >
|
Chris@16
|
549 // {};
|
Chris@16
|
550
|
Chris@16
|
551 // same as above but using mpl::vector<> instead of mpl::vector0<>
|
Chris@16
|
552 template <typename Attribute, typename Iterator, typename HasState
|
Chris@16
|
553 , typename Idtype>
|
Chris@16
|
554 struct assign_to_attribute_from_value<Attribute
|
Chris@16
|
555 , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> >
|
Chris@16
|
556 {
|
Chris@16
|
557 static void
|
Chris@16
|
558 call(lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> const& t
|
Chris@16
|
559 , Attribute& attr)
|
Chris@16
|
560 {
|
Chris@16
|
561 // The default type returned by the token_def parser component (if
|
Chris@16
|
562 // it has no token value type assigned) is the pair of iterators
|
Chris@16
|
563 // to the matched character sequence.
|
Chris@16
|
564 spirit::traits::assign_to(t.value().begin(), t.value().end(), attr);
|
Chris@16
|
565 }
|
Chris@16
|
566 };
|
Chris@16
|
567
|
Chris@16
|
568 // template <typename Attribute, typename Iterator, typename HasState
|
Chris@16
|
569 // , typename Idtype>
|
Chris@16
|
570 // struct assign_to_container_from_value<Attribute
|
Chris@16
|
571 // , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> >
|
Chris@16
|
572 // : assign_to_attribute_from_value<Attribute
|
Chris@16
|
573 // , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> >
|
Chris@16
|
574 // {};
|
Chris@16
|
575
|
Chris@16
|
576 // This is called from the parse function of token_def if the token type
|
Chris@16
|
577 // has been explicitly omitted (i.e. no attribute value is used), which
|
Chris@16
|
578 // essentially means that every attribute gets initialized using default
|
Chris@16
|
579 // constructed values.
|
Chris@16
|
580 template <typename Attribute, typename Iterator, typename HasState
|
Chris@16
|
581 , typename Idtype>
|
Chris@16
|
582 struct assign_to_attribute_from_value<Attribute
|
Chris@16
|
583 , lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> >
|
Chris@16
|
584 {
|
Chris@16
|
585 static void
|
Chris@16
|
586 call(lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> const& t
|
Chris@16
|
587 , Attribute& attr)
|
Chris@16
|
588 {
|
Chris@16
|
589 // do nothing
|
Chris@16
|
590 }
|
Chris@16
|
591 };
|
Chris@16
|
592
|
Chris@16
|
593 template <typename Attribute, typename Iterator, typename HasState
|
Chris@16
|
594 , typename Idtype>
|
Chris@16
|
595 struct assign_to_container_from_value<Attribute
|
Chris@16
|
596 , lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> >
|
Chris@16
|
597 : assign_to_attribute_from_value<Attribute
|
Chris@16
|
598 , lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> >
|
Chris@16
|
599 {};
|
Chris@16
|
600
|
Chris@16
|
601 // This is called from the parse function of lexer_def_
|
Chris@16
|
602 template <typename Iterator, typename AttributeTypes, typename HasState
|
Chris@16
|
603 , typename Idtype_, typename Idtype>
|
Chris@16
|
604 struct assign_to_attribute_from_value<
|
Chris@16
|
605 fusion::vector2<Idtype_, iterator_range<Iterator> >
|
Chris@16
|
606 , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
Chris@16
|
607 {
|
Chris@16
|
608 static void
|
Chris@16
|
609 call(lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> const& t
|
Chris@16
|
610 , fusion::vector2<Idtype_, iterator_range<Iterator> >& attr)
|
Chris@16
|
611 {
|
Chris@16
|
612 // The type returned by the lexer_def_ parser components is a
|
Chris@16
|
613 // fusion::vector containing the token id of the matched token
|
Chris@16
|
614 // and the pair of iterators to the matched character sequence.
|
Chris@16
|
615 typedef iterator_range<Iterator> iterpair_type;
|
Chris@16
|
616 typedef fusion::vector2<Idtype_, iterator_range<Iterator> >
|
Chris@16
|
617 attribute_type;
|
Chris@16
|
618
|
Chris@16
|
619 iterpair_type const& ip = boost::get<iterpair_type>(t.value());
|
Chris@16
|
620 attr = attribute_type(t.id(), ip);
|
Chris@16
|
621 }
|
Chris@16
|
622 };
|
Chris@16
|
623
|
Chris@16
|
624 template <typename Iterator, typename AttributeTypes, typename HasState
|
Chris@16
|
625 , typename Idtype_, typename Idtype>
|
Chris@16
|
626 struct assign_to_container_from_value<
|
Chris@16
|
627 fusion::vector2<Idtype_, iterator_range<Iterator> >
|
Chris@16
|
628 , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
Chris@16
|
629 : assign_to_attribute_from_value<
|
Chris@16
|
630 fusion::vector2<Idtype_, iterator_range<Iterator> >
|
Chris@16
|
631 , lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
|
Chris@16
|
632 {};
|
Chris@16
|
633
|
Chris@16
|
634 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
635 // Overload debug output for a single token, this integrates lexer tokens
|
Chris@16
|
636 // with Qi's simple_trace debug facilities
|
Chris@16
|
637 template <typename Iterator, typename Attribute, typename HasState
|
Chris@16
|
638 , typename Idtype>
|
Chris@16
|
639 struct token_printer_debug<
|
Chris@16
|
640 lex::lexertl::token<Iterator, Attribute, HasState, Idtype> >
|
Chris@16
|
641 {
|
Chris@16
|
642 typedef lex::lexertl::token<Iterator, Attribute, HasState, Idtype> token_type;
|
Chris@16
|
643
|
Chris@16
|
644 template <typename Out>
|
Chris@16
|
645 static void print(Out& out, token_type const& val)
|
Chris@16
|
646 {
|
Chris@16
|
647 out << '[';
|
Chris@16
|
648 spirit::traits::print_token(out, val.value());
|
Chris@16
|
649 out << ']';
|
Chris@16
|
650 }
|
Chris@16
|
651 };
|
Chris@16
|
652 }}}
|
Chris@16
|
653
|
Chris@16
|
654 #endif
|