/*============================================================================= | |
Boost.Wave: A Standard compliant C++ preprocessor library | |
Definition of the position_iterator and file_position templates | |
http://www.boost.org/ | |
Copyright (c) 2001-2011 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 { | |
/////////////////////////////////////////////////////////////////////////////// | |
namespace debug { | |
// Used only when BOOST_ASSERT expands to something | |
// make sure the string literal does not contain any escapes ('\\' just | |
// before '\\', '\"' or '?') | |
template <typename StringT> | |
inline bool | |
is_escaped_lit(StringT const &value) | |
{ | |
typename StringT::size_type pos = value.find_first_of ("\\", 0); | |
if (StringT::npos != pos) { | |
do { | |
if ('\\' == value[pos+1] || | |
'\"' == value[pos+1] || | |
'?' == value[pos+1]) | |
{ | |
return true; | |
} | |
else { | |
pos = value.find_first_of ("\\", pos+1); | |
} | |
} while (pos != StringT::npos); | |
} | |
return false; | |
} | |
/////////////////////////////////////////////////////////////////////////////// | |
} // namespace debug | |
/////////////////////////////////////////////////////////////////////////////// | |
// | |
// 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_) | |
{ | |
BOOST_ASSERT(!debug::is_escaped_lit(file)); | |
} | |
// 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_; | |
BOOST_ASSERT(!debug::is_escaped_lit(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) |