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