1/*============================================================================= 2 Copyright (c) 2002 Juan Carlos Arevalo-Baeza 3 Copyright (c) 2002-2006 Hartmut Kaiser 4 Copyright (c) 2003 Giovanni Bajo 5 http://spirit.sourceforge.net/ 6 7 Use, modification and distribution is subject to the Boost Software 8 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 9 http://www.boost.org/LICENSE_1_0.txt) 10=============================================================================*/ 11#ifndef BOOST_SPIRIT_CLASSIC_ITERATOR_IMPL_POSITION_ITERATOR_IPP 12#define BOOST_SPIRIT_CLASSIC_ITERATOR_IMPL_POSITION_ITERATOR_IPP 13 14#include <boost/config.hpp> 15#include <boost/iterator_adaptors.hpp> 16#include <boost/type_traits/add_const.hpp> 17#include <boost/mpl/if.hpp> 18#include <boost/type_traits/is_same.hpp> 19#include <boost/spirit/home/classic/core/nil.hpp> // for nil_t 20#include <iterator> // for std::iterator_traits 21 22namespace boost { namespace spirit { 23 24BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 25 26/////////////////////////////////////////////////////////////////////////////// 27// 28// position_policy<file_position_without_column> 29// 30// Specialization to handle file_position_without_column. Only take care of 31// newlines since no column tracking is needed. 32// 33/////////////////////////////////////////////////////////////////////////////// 34template <typename String> 35class position_policy<file_position_without_column_base<String> > { 36 37public: 38 void next_line(file_position_without_column_base<String>& pos) 39 { 40 ++pos.line; 41 } 42 43 void set_tab_chars(unsigned int /*chars*/){} 44 void next_char(file_position_without_column_base<String>& /*pos*/) {} 45 void tabulation(file_position_without_column_base<String>& /*pos*/) {} 46}; 47 48/////////////////////////////////////////////////////////////////////////////// 49// 50// position_policy<file_position> 51// 52// Specialization to handle file_position. Track characters and tabulation 53// to compute the current column correctly. 54// 55// Default tab size is 4. You can change this with the set_tabchars member 56// of position_iterator. 57// 58/////////////////////////////////////////////////////////////////////////////// 59template <typename String> 60class position_policy<file_position_base<String> > { 61 62public: 63 position_policy() 64 : m_CharsPerTab(4) 65 {} 66 67 void next_line(file_position_base<String>& pos) 68 { 69 ++pos.line; 70 pos.column = 1; 71 } 72 73 void set_tab_chars(unsigned int chars) 74 { 75 m_CharsPerTab = chars; 76 } 77 78 void next_char(file_position_base<String>& pos) 79 { 80 ++pos.column; 81 } 82 83 void tabulation(file_position_base<String>& pos) 84 { 85 pos.column += m_CharsPerTab - (pos.column - 1) % m_CharsPerTab; 86 } 87 88private: 89 unsigned int m_CharsPerTab; 90}; 91 92/* namespace boost::spirit { */ namespace iterator_ { namespace impl { 93 94template <typename T> 95struct make_const : boost::add_const<T> 96{}; 97 98template <typename T> 99struct make_const<T&> 100{ 101 typedef typename boost::add_const<T>::type& type; 102}; 103 104/////////////////////////////////////////////////////////////////////////////// 105// 106// position_iterator_base_generator 107// 108// Metafunction to generate the iterator type using boost::iterator_adaptors, 109// hiding all the metaprogramming thunking code in it. It is used 110// mainly to keep the public interface (position_iterator) cleanear. 111// 112/////////////////////////////////////////////////////////////////////////////// 113template <typename MainIterT, typename ForwardIterT, typename PositionT> 114struct position_iterator_base_generator 115{ 116private: 117 typedef std::iterator_traits<ForwardIterT> traits; 118 typedef typename traits::value_type value_type; 119 typedef typename traits::iterator_category iter_category_t; 120 typedef typename traits::reference reference; 121 122 // Position iterator is always a non-mutable iterator 123 typedef typename boost::add_const<value_type>::type const_value_type; 124 125public: 126 // Check if the MainIterT is nil. If it's nil, it means that the actual 127 // self type is position_iterator. Otherwise, it's a real type we 128 // must use 129 typedef typename boost::mpl::if_< 130 typename boost::is_same<MainIterT, nil_t>::type, 131 position_iterator<ForwardIterT, PositionT, nil_t>, 132 MainIterT 133 >::type main_iter_t; 134 135 typedef boost::iterator_adaptor< 136 main_iter_t, 137 ForwardIterT, 138 const_value_type, 139 boost::forward_traversal_tag, 140 typename make_const<reference>::type 141 > type; 142}; 143 144}} 145 146BOOST_SPIRIT_CLASSIC_NAMESPACE_END 147 148}} /* namespace boost::spirit::iterator_::impl */ 149 150#endif 151