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