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