1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
4 Definition of the unput queue iterator
8 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
9 Software License, Version 1.0. (See accompanying file
10 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 =============================================================================*/
12 #if !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED)
13 #define UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED
17 #include <boost/assert.hpp>
18 #include <boost/iterator_adaptors.hpp>
20 #include <boost/wave/wave_config.hpp>
21 #include <boost/wave/token_ids.hpp> // token_id
23 // this must occur after all of the includes and before any code appears
24 #ifdef BOOST_HAS_ABI_HEADERS
25 #include BOOST_ABI_PREFIX
28 ///////////////////////////////////////////////////////////////////////////////
33 ///////////////////////////////////////////////////////////////////////////////
35 // unput_queue_iterator
37 // The unput_queue_iterator templates encapsulates an unput_queue together
38 // with the direct input to be read after the unput queue is emptied
40 // This version is for the new iterator_adaptors (was released with
43 ///////////////////////////////////////////////////////////////////////////////
44 template <typename IteratorT, typename TokenT, typename ContainerT>
45 class unput_queue_iterator
46 : public boost::iterator_adaptor<
47 unput_queue_iterator<IteratorT, TokenT, ContainerT>,
48 IteratorT, TokenT const, std::forward_iterator_tag>
50 typedef boost::iterator_adaptor<
51 unput_queue_iterator<IteratorT, TokenT, ContainerT>,
52 IteratorT, TokenT const, std::forward_iterator_tag>
56 typedef ContainerT container_type;
57 typedef IteratorT iterator_type;
59 unput_queue_iterator(IteratorT const &it, ContainerT &queue)
60 : base_type(it), unput_queue(queue)
63 ContainerT &get_unput_queue()
64 { return unput_queue; }
65 ContainerT const &get_unput_queue() const
66 { return unput_queue; }
67 IteratorT &get_base_iterator()
68 { return base_type::base_reference(); }
69 IteratorT const &get_base_iterator() const
70 { return base_type::base_reference(); }
72 unput_queue_iterator &operator= (unput_queue_iterator const &rhs)
75 unput_queue = rhs.unput_queue;
76 base_type::operator=(rhs);
81 typename base_type::reference dereference() const
83 if (!unput_queue.empty())
84 return unput_queue.front();
85 return *base_type::base_reference();
90 if (!unput_queue.empty()) {
91 // there exist pending tokens in the unput queue
92 unput_queue.pop_front();
95 // the unput_queue is empty, so advance the base iterator
96 ++base_type::base_reference();
101 typename OtherDerivedT, typename OtherIteratorT,
102 typename V, typename C, typename R, typename D
105 boost::iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
108 // two iterators are equal, if both begin() iterators of the queue
109 // objects are equal and the base iterators are equal as well
110 OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x);
112 ((unput_queue.empty() && rhs.unput_queue.empty()) ||
113 (&unput_queue == &rhs.unput_queue &&
114 unput_queue.begin() == rhs.unput_queue.begin()
117 (get_base_iterator() == rhs.get_base_iterator());
121 ContainerT &unput_queue;
126 ///////////////////////////////////////////////////////////////////////////
127 template <typename IteratorT, typename TokenT, typename ContainerT>
128 struct gen_unput_queue_iterator
130 typedef ContainerT container_type;
131 typedef IteratorT iterator_type;
132 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
135 static container_type last;
138 generate(iterator_type const &it)
140 return return_type(it, last);
144 generate(ContainerT &queue, iterator_type const &it)
146 return return_type(it, queue);
150 template <typename IteratorT, typename TokenT, typename ContainerT>
151 typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::
153 gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::last =
154 typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::
157 ///////////////////////////////////////////////////////////////////////////
158 template <typename IteratorT, typename TokenT, typename ContainerT>
159 struct gen_unput_queue_iterator<
160 unput_queue_iterator<IteratorT, TokenT, ContainerT>,
163 typedef ContainerT container_type;
164 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
166 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
169 static container_type last;
172 generate(iterator_type &it)
174 return return_type(it.base(), last);
178 generate(ContainerT &queue, iterator_type &it)
180 return return_type(it.base(), queue);
184 ///////////////////////////////////////////////////////////////////////////
185 template <typename IteratorT>
186 struct assign_iterator
189 do_ (IteratorT &dest, IteratorT const &src)
195 ///////////////////////////////////////////////////////////////////////////
197 // Look for the first non-whitespace token and return this token id.
198 // Note though, that the embedded unput_queues are not touched in any way!
200 template <typename IteratorT>
203 static boost::wave::token_id
204 peek(IteratorT it, IteratorT end, bool skip_whitespace = true)
206 using namespace boost::wave;
207 if (skip_whitespace) {
208 for (++it; it != end; ++it) {
209 if (!IS_CATEGORY(*it, WhiteSpaceTokenType) &&
210 T_NEWLINE != token_id(*it))
212 break; // stop at the first non-whitespace token
217 ++it; // we have at least to look ahead
220 return token_id(*it);
225 template <typename IteratorT, typename TokenT, typename ContainerT>
227 unput_queue_iterator<IteratorT, TokenT, ContainerT> > {
229 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> iterator_type;
231 static boost::wave::token_id
232 peek(iterator_type it, iterator_type end, bool skip_whitespace = true)
234 using namespace boost::wave;
236 typename iterator_type::container_type &queue = it.get_unput_queue();
238 // first try to find it in the unput_queue
239 if (0 != queue.size()) {
240 typename iterator_type::container_type::iterator cit = queue.begin();
241 typename iterator_type::container_type::iterator cend = queue.end();
243 if (skip_whitespace) {
244 for (++cit; cit != cend; ++cit) {
245 if (!IS_CATEGORY(*cit, WhiteSpaceTokenType) &&
246 T_NEWLINE != token_id(*cit))
248 break; // stop at the first non-whitespace token
253 ++cit; // we have at least to look ahead
256 return token_id(*cit);
259 // second try to move on into the base iterator stream
260 typename iterator_type::iterator_type base_it = it.get_base_iterator();
261 typename iterator_type::iterator_type base_end = end.get_base_iterator();
263 if (0 == queue.size())
264 ++base_it; // advance, if the unput queue is empty
266 if (skip_whitespace) {
267 for (/**/; base_it != base_end; ++base_it) {
268 if (!IS_CATEGORY(*base_it, WhiteSpaceTokenType) &&
269 T_NEWLINE != token_id(*base_it))
271 break; // stop at the first non-whitespace token
275 if (base_it == base_end)
278 return token_id(*base_it);
282 ///////////////////////////////////////////////////////////////////////////////
285 ///////////////////////////////////////////////////////////////////////////////
290 // the suffix header occurs after all of the code
291 #ifdef BOOST_HAS_ABI_HEADERS
292 #include BOOST_ABI_SUFFIX
295 #endif // !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED)