/*============================================================================= Copyright (c) 2002 Juan Carlos Arevalo-Baeza Copyright (c) 2002-2006 Hartmut Kaiser Copyright (c) 2003 Giovanni Bajo http://spirit.sourceforge.net/ Use, modification and distribution is subject to 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) =============================================================================*/ #ifndef POSITION_ITERATOR_IPP #define POSITION_ITERATOR_IPP #include <boost/config.hpp> #include <boost/iterator_adaptors.hpp> #include <boost/type_traits/add_const.hpp> #include <boost/mpl/if.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/spirit/core/nil.hpp> // for nil_t #include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits namespace boost { namespace spirit { /////////////////////////////////////////////////////////////////////////////// // // position_policy<file_position_without_column> // // Specialization to handle file_position_without_column. Only take care of // newlines since no column tracking is needed. // /////////////////////////////////////////////////////////////////////////////// template <typename String> class position_policy<file_position_without_column_base<String> > { public: void next_line(file_position_without_column_base<String>& pos) { ++pos.line; } void set_tab_chars(unsigned int /*chars*/){} void next_char(file_position_without_column_base<String>& /*pos*/) {} void tabulation(file_position_without_column_base<String>& /*pos*/) {} }; /////////////////////////////////////////////////////////////////////////////// // // position_policy<file_position> // // Specialization to handle file_position. Track characters and tabulation // to compute the current column correctly. // // Default tab size is 4. You can change this with the set_tabchars member // of position_iterator. // /////////////////////////////////////////////////////////////////////////////// template <typename String> class position_policy<file_position_base<String> > { public: position_policy() : m_CharsPerTab(4) {} void next_line(file_position_base<String>& pos) { ++pos.line; pos.column = 1; } void set_tab_chars(unsigned int chars) { m_CharsPerTab = chars; } void next_char(file_position_base<String>& pos) { ++pos.column; } void tabulation(file_position_base<String>& pos) { pos.column += m_CharsPerTab - (pos.column - 1) % m_CharsPerTab; } private: unsigned int m_CharsPerTab; }; /* namespace boost::spirit { */ namespace iterator_ { namespace impl { /////////////////////////////////////////////////////////////////////////////// // // position_iterator_base_generator // // Metafunction to generate the iterator type using boost::iterator_adaptors, // hiding all the metaprogramming thunking code in it. It is used // mainly to keep the public interface (position_iterator) cleanear. // /////////////////////////////////////////////////////////////////////////////// template <typename MainIterT, typename ForwardIterT, typename PositionT> struct position_iterator_base_generator { private: typedef boost::detail::iterator_traits<ForwardIterT> traits; typedef typename traits::value_type value_type; typedef typename traits::iterator_category iter_category_t; // Position iterator is always a non-mutable iterator typedef typename boost::add_const<value_type>::type const_value_type; public: // Check if the MainIterT is nil. If it's nil, it means that the actual // self type is position_iterator. Otherwise, it's a real type we // must use typedef typename boost::mpl::if_< typename boost::is_same<MainIterT, nil_t>::type, position_iterator<ForwardIterT, PositionT, nil_t>, MainIterT >::type main_iter_t; typedef boost::iterator_adaptor< main_iter_t, ForwardIterT, const_value_type > type; }; }}}} /* namespace boost::spirit::iterator_::impl */ #endif