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/variant.hpp> 27 #include <boost/mpl/bool.hpp> 28 #include <boost/mpl/vector.hpp> 29 #include <boost/mpl/is_sequence.hpp> 30 #include <boost/mpl/begin.hpp> 31 #include <boost/mpl/insert.hpp> 32 #include <boost/mpl/vector.hpp> 33 #include <boost/mpl/if.hpp> 34 #include <boost/mpl/or.hpp> 35 #include <boost/range/iterator_range_core.hpp> 36 #include <boost/type_traits/integral_promotion.hpp> 37 #include <boost/type_traits/is_same.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 static_cast<id_type>(id_); } 159 160 // Retrieve or set the token id of this token instance. idboost::spirit::lex::lexertl::token161 id_type id() const { return static_cast<id_type>(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 typename boost::integral_promotion<id_type>::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& 583 , Attribute&) 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