blob: cbf648738f3586ca2768db10e935725dcafa6c3e [file] [log] [blame]
/*=============================================================================
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/home/classic/core/nil.hpp> // for nil_t
#include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
namespace boost { namespace spirit {
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
//
// 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,
boost::forward_traversal_tag
> type;
};
}}
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}} /* namespace boost::spirit::iterator_::impl */
#endif