annotate DEPENDENCIES/generic/include/boost/spirit/home/lex/lexer/lexertl/token.hpp @ 65:d8563d4879f3

Merge
author Chris Cannam
date Mon, 22 Sep 2014 11:47:11 +0100
parents 2665513ce2d3
children c530137014c0
rev   line source
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