You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
335 lines
9.6 KiB
335 lines
9.6 KiB
/*============================================================================= |
|
Boost.Wave: A Standard compliant C++ preprocessor library |
|
|
|
A generic C++ lexer token definition |
|
|
|
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(CPP_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED) |
|
#define CPP_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED |
|
|
|
#include <boost/wave/wave_config.hpp> |
|
#if BOOST_WAVE_SERIALIZATION != 0 |
|
#include <boost/serialization/serialization.hpp> |
|
#endif |
|
#include <boost/wave/util/file_position.hpp> |
|
#include <boost/wave/token_ids.hpp> |
|
#include <boost/wave/language_support.hpp> |
|
|
|
#include <boost/throw_exception.hpp> |
|
#include <boost/pool/singleton_pool.hpp> |
|
#include <boost/detail/atomic_count.hpp> |
|
|
|
// 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 cpplexer { |
|
|
|
namespace impl { |
|
|
|
template <typename StringTypeT, typename PositionT> |
|
class token_data |
|
{ |
|
public: |
|
typedef StringTypeT string_type; |
|
typedef PositionT position_type; |
|
|
|
// default constructed tokens correspond to EOI tokens |
|
token_data() |
|
: id(T_EOI), refcnt(1) |
|
{} |
|
|
|
// construct an invalid token |
|
explicit token_data(int) |
|
: id(T_UNKNOWN), refcnt(1) |
|
{} |
|
|
|
token_data(token_id id_, string_type const &value_, position_type const &pos_) |
|
: id(id_), value(value_), pos(pos_), refcnt(1) |
|
{} |
|
|
|
token_data(token_data const& rhs) |
|
: id(rhs.id), value(rhs.value), pos(rhs.pos), refcnt(1) |
|
{} |
|
|
|
~token_data() |
|
{} |
|
|
|
std::size_t addref() { return ++refcnt; } |
|
std::size_t release() { return --refcnt; } |
|
std::size_t get_refcnt() const { return refcnt; } |
|
|
|
// accessors |
|
operator token_id() const { return id; } |
|
string_type const &get_value() const { return value; } |
|
position_type const &get_position() const { return pos; } |
|
|
|
void set_token_id (token_id id_) { id = id_; } |
|
void set_value (string_type const &value_) { value = value_; } |
|
void set_position (position_type const &pos_) { pos = pos_; } |
|
|
|
friend bool operator== (token_data const& lhs, token_data const& rhs) |
|
{ |
|
// two tokens are considered equal even if they refer to different |
|
// positions |
|
return (lhs.id == rhs.id && lhs.value == rhs.value) ? true : false; |
|
} |
|
|
|
void init(token_id id_, string_type const &value_, position_type const &pos_) |
|
{ |
|
BOOST_ASSERT(refcnt == 1); |
|
id = id_; |
|
value = value_; |
|
pos = pos_; |
|
} |
|
|
|
void init(token_data const& rhs) |
|
{ |
|
BOOST_ASSERT(refcnt == 1); |
|
id = rhs.id; |
|
value = rhs.value; |
|
pos = rhs.pos; |
|
} |
|
|
|
static void *operator new(std::size_t size); |
|
static void operator delete(void *p, std::size_t size); |
|
|
|
#if defined(BOOST_SPIRIT_DEBUG) |
|
// debug support |
|
void print (std::ostream &stream) const |
|
{ |
|
stream << get_token_name(id) << "("; |
|
for (std::size_t i = 0; i < value.size(); ++i) { |
|
switch (value[i]) { |
|
case '\r': stream << "\\r"; break; |
|
case '\n': stream << "\\n"; break; |
|
default: |
|
stream << value[i]; |
|
break; |
|
} |
|
} |
|
stream << ")"; |
|
} |
|
#endif // defined(BOOST_SPIRIT_DEBUG) |
|
|
|
#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("id", id); |
|
ar & make_nvp("value", value); |
|
ar & make_nvp("position", pos); |
|
} |
|
#endif |
|
|
|
private: |
|
token_id id; // the token id |
|
string_type value; // the text, which was parsed into this token |
|
position_type pos; // the original file position |
|
boost::detail::atomic_count refcnt; |
|
}; |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
struct token_data_tag {}; |
|
|
|
template <typename StringTypeT, typename PositionT> |
|
inline void * |
|
token_data<StringTypeT, PositionT>::operator new(std::size_t size) |
|
{ |
|
BOOST_ASSERT(sizeof(token_data<StringTypeT, PositionT>) == size); |
|
typedef boost::singleton_pool< |
|
token_data_tag, sizeof(token_data<StringTypeT, PositionT>) |
|
> pool_type; |
|
|
|
void *ret = pool_type::malloc(); |
|
if (0 == ret) |
|
boost::throw_exception(std::bad_alloc()); |
|
return ret; |
|
} |
|
|
|
template <typename StringTypeT, typename PositionT> |
|
inline void |
|
token_data<StringTypeT, PositionT>::operator delete(void *p, std::size_t size) |
|
{ |
|
BOOST_ASSERT(sizeof(token_data<StringTypeT, PositionT>) == size); |
|
typedef boost::singleton_pool< |
|
token_data_tag, sizeof(token_data<StringTypeT, PositionT>) |
|
> pool_type; |
|
|
|
if (0 != p) |
|
pool_type::free(p); |
|
} |
|
|
|
} // namespace impl |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
// forward declaration of the token type |
|
template <typename PositionT = boost::wave::util::file_position_type> |
|
class lex_token; |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// lex_token |
|
// |
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
template <typename PositionT> |
|
class lex_token |
|
{ |
|
public: |
|
typedef BOOST_WAVE_STRINGTYPE string_type; |
|
typedef PositionT position_type; |
|
|
|
private: |
|
typedef impl::token_data<string_type, position_type> data_type; |
|
|
|
public: |
|
// default constructed tokens correspond to EOI tokens |
|
lex_token() |
|
: data(0) |
|
{} |
|
|
|
// construct an invalid token |
|
explicit lex_token(int) |
|
: data(new data_type(0)) |
|
{} |
|
|
|
lex_token(lex_token const& rhs) |
|
: data(rhs.data) |
|
{ |
|
if (0 != data) |
|
data->addref(); |
|
} |
|
|
|
lex_token(token_id id_, string_type const &value_, PositionT const &pos_) |
|
: data(new data_type(id_, value_, pos_)) |
|
{} |
|
|
|
~lex_token() |
|
{ |
|
if (0 != data && 0 == data->release()) |
|
delete data; |
|
data = 0; |
|
} |
|
|
|
lex_token& operator=(lex_token const& rhs) |
|
{ |
|
if (&rhs != this) { |
|
if (0 != data && 0 == data->release()) |
|
delete data; |
|
|
|
data = rhs.data; |
|
if (0 != data) |
|
data->addref(); |
|
} |
|
return *this; |
|
} |
|
|
|
// accessors |
|
operator token_id() const { return 0 != data ? token_id(*data) : T_EOI; } |
|
string_type const &get_value() const { return data->get_value(); } |
|
position_type const &get_position() const { return data->get_position(); } |
|
bool is_eoi() const { return 0 == data || token_id(*data) == T_EOI; } |
|
bool is_valid() const { return 0 != data && token_id(*data) != T_UNKNOWN; } |
|
|
|
void set_token_id (token_id id_) { make_unique(); data->set_token_id(id_); } |
|
void set_value (string_type const &value_) { make_unique(); data->set_value(value_); } |
|
void set_position (position_type const &pos_) { make_unique(); data->set_position(pos_); } |
|
|
|
friend bool operator== (lex_token const& lhs, lex_token const& rhs) |
|
{ |
|
if (0 == rhs.data) |
|
return 0 == lhs.data; |
|
if (0 == lhs.data) |
|
return false; |
|
return *(lhs.data) == *(rhs.data); |
|
} |
|
|
|
// debug support |
|
#if BOOST_WAVE_DUMP_PARSE_TREE != 0 |
|
// access functions for the tree_to_xml functionality |
|
static int get_token_id(lex_token const &t) |
|
{ return token_id(t); } |
|
static string_type get_token_value(lex_token const &t) |
|
{ return t.get_value(); } |
|
#endif |
|
|
|
#if defined(BOOST_SPIRIT_DEBUG) |
|
// debug support |
|
void print (std::ostream &stream) const |
|
{ |
|
data->print(stream); |
|
} |
|
#endif // defined(BOOST_SPIRIT_DEBUG) |
|
|
|
private: |
|
#if BOOST_WAVE_SERIALIZATION != 0 |
|
friend class boost::serialization::access; |
|
template<typename Archive> |
|
void serialize(Archive &ar, const unsigned int version) |
|
{ |
|
data->serialize(ar, version); |
|
} |
|
#endif |
|
|
|
// make a unique copy of the current object |
|
void make_unique() |
|
{ |
|
if (1 == data->get_refcnt()) |
|
return; |
|
|
|
data_type* newdata = new data_type(*data) ; |
|
|
|
data->release(); // release this reference, can't get zero |
|
data = newdata; |
|
} |
|
|
|
data_type* data; |
|
}; |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
// This overload is needed by the multi_pass/functor_input_policy to |
|
// validate a token instance. It has to be defined in the same namespace |
|
// as the token class itself to allow ADL to find it. |
|
/////////////////////////////////////////////////////////////////////////////// |
|
template <typename Position> |
|
inline bool |
|
token_is_valid(lex_token<Position> const& t) |
|
{ |
|
return t.is_valid(); |
|
} |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
#if defined(BOOST_SPIRIT_DEBUG) |
|
template <typename PositionT> |
|
inline std::ostream & |
|
operator<< (std::ostream &stream, lex_token<PositionT> const &object) |
|
{ |
|
object.print(stream); |
|
return stream; |
|
} |
|
#endif // defined(BOOST_SPIRIT_DEBUG) |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
} // namespace cpplexer |
|
} // namespace wave |
|
} // namespace boost |
|
|
|
// the suffix header occurs after all of the code |
|
#ifdef BOOST_HAS_ABI_HEADERS |
|
#include BOOST_ABI_SUFFIX |
|
#endif |
|
|
|
#endif // !defined(CPP_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED)
|
|
|