file_position.hpp 5.67 KB
Newer Older
xuebingbing's avatar
xuebingbing committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
/*=============================================================================
    Boost.Wave: A Standard compliant C++ preprocessor library

    Definition of the position_iterator and file_position templates
    
    http://www.boost.org/

    Copyright (c) 2001-2012 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(FILE_POSITION_H_52BDEDF7_DAD3_4F24_802F_E66BB8098F68_INCLUDED)
#define FILE_POSITION_H_52BDEDF7_DAD3_4F24_802F_E66BB8098F68_INCLUDED

#include <string>
#include <ostream>

#include <boost/assert.hpp>
#include <boost/spirit/include/classic_version.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#include <boost/wave/wave_config.hpp>
#if BOOST_WAVE_SERIALIZATION != 0
#include <boost/serialization/serialization.hpp>
#endif

// this must occur after all of the includes and before any code appears
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif

///////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace wave {
namespace util {

///////////////////////////////////////////////////////////////////////////////
//
//  file_position
//
//  A structure to hold positional information. This includes the filename,
//  line number and column number of a current token position.
//
///////////////////////////////////////////////////////////////////////////////

template <typename StringT>
struct file_position {

public:
    typedef StringT string_type;

    file_position()
    :   file(), line(1), column(1)
    {}
    explicit file_position(string_type const& file_, std::size_t line_ = 1, 
            std::size_t column_ = 1)
    :   file(file_), line(line_), column(column_)
    {}

// accessors
    string_type const &get_file() const { return file; }
    std::size_t get_line() const { return line; }
    std::size_t get_column() const { return column; }

    void set_file(string_type const &file_) 
    { 
        file = file_; 
    }
    void set_line(std::size_t line_) { line = line_; }
    void set_column(std::size_t column_) { column = column_; }

private:
#if BOOST_WAVE_SERIALIZATION != 0
    friend class boost::serialization::access;
    template<typename Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        using namespace boost::serialization;
        ar & make_nvp("filename", file);
        ar & make_nvp("line", line);
        ar & make_nvp("column", column);
    }
#endif

    string_type file;
    std::size_t line;
    std::size_t column;
};

template <typename StringT>
bool operator== (file_position<StringT> const &lhs, 
    file_position<StringT> const &rhs)
{
    return lhs.get_column() == rhs.get_column() && 
        lhs.get_line() == rhs.get_line() && lhs.get_file() == rhs.get_file();
}

template <typename StringT>
inline std::ostream &
operator<< (std::ostream &o, file_position<StringT> const &pos)
{
    o << pos.get_file() << ":" << pos.get_line() << ":"  << pos.get_column();
    return o;
}

typedef file_position<BOOST_WAVE_STRINGTYPE> file_position_type;

///////////////////////////////////////////////////////////////////////////////
//
//  position_iterator
//
//  The position_iterator used by Wave is now based on the corresponding Spirit 
//  type. This type is used with our own file_position though. The needed
//  specialization of the boost::spirit::classic::position_policy class is 
//  provided below.
//
///////////////////////////////////////////////////////////////////////////////

template <typename IteratorT, typename PositionT>
struct position_iterator 
:   boost::spirit::classic::position_iterator<IteratorT, PositionT>
{
    typedef boost::spirit::classic::position_iterator<IteratorT, PositionT> base_type;

    position_iterator()
    {
    }

    position_iterator(IteratorT const &begin, IteratorT const &end,
            PositionT const &pos)
    :   base_type(begin, end, pos)
    {
    }
};

///////////////////////////////////////////////////////////////////////////////
}   // namespace util
}   // namespace wave

///////////////////////////////////////////////////////////////////////////////

namespace spirit { namespace classic {

///////////////////////////////////////////////////////////////////////////////
//
//  The boost::spirit::classic::position_policy has to be specialized for our 
//  file_position class
//
///////////////////////////////////////////////////////////////////////////////

    template <>
    class position_policy<boost::wave::util::file_position_type> {

    public:
        position_policy()
            : m_CharsPerTab(4)
        {}

        void next_line(boost::wave::util::file_position_type &pos)
        {
            pos.set_line(pos.get_line() + 1);
            pos.set_column(1);
        }

        void set_tab_chars(unsigned int chars)
        {
            m_CharsPerTab = chars;
        }

        void next_char(boost::wave::util::file_position_type &pos)
        {
            pos.set_column(pos.get_column() + 1);
        }

        void tabulation(boost::wave::util::file_position_type &pos)   
        {
            pos.set_column(pos.get_column() + m_CharsPerTab - 
                (pos.get_column() - 1) % m_CharsPerTab);
        }

    private:
        unsigned int m_CharsPerTab;
    };

///////////////////////////////////////////////////////////////////////////////
}}   // namespace spirit::classic

}   // namespace boost 

// the suffix header occurs after all of the code
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif

#endif // !defined(FILE_POSITION_H_52BDEDF7_DAD3_4F24_802F_E66BB8098F68_INCLUDED)