Chris@16: /*============================================================================= Chris@16: Boost.Wave: A Standard compliant C++ preprocessor library Chris@16: Chris@16: Definition of the unput queue iterator Chris@16: Chris@16: http://www.boost.org/ Chris@16: Chris@16: Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost Chris@16: Software License, Version 1.0. (See accompanying file Chris@16: LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: #if !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED) Chris@16: #define UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include // token_id Chris@16: Chris@16: // this must occur after all of the includes and before any code appears Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_PREFIX Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { Chris@16: namespace wave { Chris@16: namespace util { Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // unput_queue_iterator Chris@16: // Chris@16: // The unput_queue_iterator templates encapsulates an unput_queue together Chris@16: // with the direct input to be read after the unput queue is emptied Chris@16: // Chris@16: // This version is for the new iterator_adaptors (was released with Chris@16: // Boost V1.31.0) Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: class unput_queue_iterator Chris@16: : public boost::iterator_adaptor< Chris@16: unput_queue_iterator, Chris@16: IteratorT, TokenT const, std::forward_iterator_tag> Chris@16: { Chris@16: typedef boost::iterator_adaptor< Chris@16: unput_queue_iterator, Chris@16: IteratorT, TokenT const, std::forward_iterator_tag> Chris@16: base_type; Chris@16: Chris@16: public: Chris@16: typedef ContainerT container_type; Chris@16: typedef IteratorT iterator_type; Chris@16: Chris@16: unput_queue_iterator(IteratorT const &it, ContainerT &queue) Chris@16: : base_type(it), unput_queue(queue) Chris@16: {} Chris@16: Chris@16: ContainerT &get_unput_queue() Chris@16: { return unput_queue; } Chris@16: ContainerT const &get_unput_queue() const Chris@16: { return unput_queue; } Chris@16: IteratorT &get_base_iterator() Chris@16: { return base_type::base_reference(); } Chris@16: IteratorT const &get_base_iterator() const Chris@16: { return base_type::base_reference(); } Chris@16: Chris@16: unput_queue_iterator &operator= (unput_queue_iterator const &rhs) Chris@16: { Chris@16: if (this != &rhs) { Chris@16: unput_queue = rhs.unput_queue; Chris@16: base_type::operator=(rhs); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: typename base_type::reference dereference() const Chris@16: { Chris@16: if (!unput_queue.empty()) Chris@16: return unput_queue.front(); Chris@16: return *base_type::base_reference(); Chris@16: } Chris@16: Chris@16: void increment() Chris@16: { Chris@16: if (!unput_queue.empty()) { Chris@16: // there exist pending tokens in the unput queue Chris@16: unput_queue.pop_front(); Chris@16: } Chris@16: else { Chris@16: // the unput_queue is empty, so advance the base iterator Chris@16: ++base_type::base_reference(); Chris@16: } Chris@16: } Chris@16: Chris@16: template < Chris@16: typename OtherDerivedT, typename OtherIteratorT, Chris@16: typename V, typename C, typename R, typename D Chris@16: > Chris@16: bool equal( Chris@16: boost::iterator_adaptor Chris@16: const &x) const Chris@16: { Chris@16: // two iterators are equal, if both begin() iterators of the queue Chris@16: // objects are equal and the base iterators are equal as well Chris@16: OtherDerivedT const &rhs = static_cast(x); Chris@16: return Chris@16: ((unput_queue.empty() && rhs.unput_queue.empty()) || Chris@16: (&unput_queue == &rhs.unput_queue && Chris@16: unput_queue.begin() == rhs.unput_queue.begin() Chris@16: ) Chris@16: ) && Chris@16: (get_base_iterator() == rhs.get_base_iterator()); Chris@16: } Chris@16: Chris@16: private: Chris@16: ContainerT &unput_queue; Chris@16: }; Chris@16: Chris@16: namespace impl { Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct gen_unput_queue_iterator Chris@16: { Chris@16: typedef ContainerT container_type; Chris@16: typedef IteratorT iterator_type; Chris@16: typedef unput_queue_iterator Chris@16: return_type; Chris@16: Chris@16: static container_type last; Chris@16: Chris@16: static return_type Chris@16: generate(iterator_type const &it) Chris@16: { Chris@16: return return_type(it, last); Chris@16: } Chris@16: Chris@16: static return_type Chris@16: generate(ContainerT &queue, iterator_type const &it) Chris@16: { Chris@16: return return_type(it, queue); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: typename gen_unput_queue_iterator:: Chris@16: container_type Chris@16: gen_unput_queue_iterator::last = Chris@16: typename gen_unput_queue_iterator:: Chris@16: container_type(); Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct gen_unput_queue_iterator< Chris@16: unput_queue_iterator, Chris@16: TokenT, ContainerT> Chris@16: { Chris@16: typedef ContainerT container_type; Chris@16: typedef unput_queue_iterator Chris@16: iterator_type; Chris@16: typedef unput_queue_iterator Chris@16: return_type; Chris@16: Chris@16: static container_type last; Chris@16: Chris@16: static return_type Chris@16: generate(iterator_type &it) Chris@16: { Chris@16: return return_type(it.base(), last); Chris@16: } Chris@16: Chris@16: static return_type Chris@16: generate(ContainerT &queue, iterator_type &it) Chris@16: { Chris@16: return return_type(it.base(), queue); Chris@16: } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct assign_iterator Chris@16: { Chris@16: static void Chris@16: do_ (IteratorT &dest, IteratorT const &src) Chris@16: { Chris@16: dest = src; Chris@16: } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // Look for the first non-whitespace token and return this token id. Chris@16: // Note though, that the embedded unput_queues are not touched in any way! Chris@16: // Chris@16: template Chris@16: struct next_token Chris@16: { Chris@16: static boost::wave::token_id Chris@16: peek(IteratorT it, IteratorT end, bool skip_whitespace = true) Chris@16: { Chris@16: using namespace boost::wave; Chris@16: if (skip_whitespace) { Chris@16: for (++it; it != end; ++it) { Chris@16: if (!IS_CATEGORY(*it, WhiteSpaceTokenType) && Chris@16: T_NEWLINE != token_id(*it)) Chris@16: { Chris@16: break; // stop at the first non-whitespace token Chris@16: } Chris@16: } Chris@16: } Chris@16: else { Chris@16: ++it; // we have at least to look ahead Chris@16: } Chris@16: if (it != end) Chris@16: return token_id(*it); Chris@16: return T_EOI; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct next_token< Chris@16: unput_queue_iterator > { Chris@16: Chris@16: typedef unput_queue_iterator iterator_type; Chris@16: Chris@16: static boost::wave::token_id Chris@16: peek(iterator_type it, iterator_type end, bool skip_whitespace = true) Chris@16: { Chris@16: using namespace boost::wave; Chris@16: Chris@16: typename iterator_type::container_type &queue = it.get_unput_queue(); Chris@16: Chris@16: // first try to find it in the unput_queue Chris@16: if (0 != queue.size()) { Chris@16: typename iterator_type::container_type::iterator cit = queue.begin(); Chris@16: typename iterator_type::container_type::iterator cend = queue.end(); Chris@16: Chris@16: if (skip_whitespace) { Chris@16: for (++cit; cit != cend; ++cit) { Chris@16: if (!IS_CATEGORY(*cit, WhiteSpaceTokenType) && Chris@16: T_NEWLINE != token_id(*cit)) Chris@16: { Chris@16: break; // stop at the first non-whitespace token Chris@16: } Chris@16: } Chris@16: } Chris@16: else { Chris@16: ++cit; // we have at least to look ahead Chris@16: } Chris@16: if (cit != cend) Chris@16: return token_id(*cit); Chris@16: } Chris@16: Chris@16: // second try to move on into the base iterator stream Chris@16: typename iterator_type::iterator_type base_it = it.get_base_iterator(); Chris@16: typename iterator_type::iterator_type base_end = end.get_base_iterator(); Chris@16: Chris@16: if (0 == queue.size()) Chris@16: ++base_it; // advance, if the unput queue is empty Chris@16: Chris@16: if (skip_whitespace) { Chris@16: for (/**/; base_it != base_end; ++base_it) { Chris@16: if (!IS_CATEGORY(*base_it, WhiteSpaceTokenType) && Chris@16: T_NEWLINE != token_id(*base_it)) Chris@16: { Chris@16: break; // stop at the first non-whitespace token Chris@16: } Chris@16: } Chris@16: } Chris@16: if (base_it == base_end) Chris@16: return T_EOI; Chris@16: Chris@16: return token_id(*base_it); Chris@16: } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: } // namespace impl Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: } // namespace util Chris@16: } // namespace wave Chris@16: } // namespace boost Chris@16: Chris@16: // the suffix header occurs after all of the code Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_SUFFIX Chris@16: #endif Chris@16: Chris@16: #endif // !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED)