/*============================================================================= Boost.Wave: A Standard compliant C++ preprocessor library A C++ lexer token definition for the real_positions example http://www.boost.org/ Copyright (c) 2001-2010 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(REAL_POSITION_TOKEN_HPP_HK_061109_INCLUDED) #define REAL_POSITION_TOKEN_HPP_HK_061109_INCLUDED #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// namespace impl { template class token_data { public: typedef StringTypeT string_type; typedef PositionT position_type; token_data() : id(boost::wave::T_EOI), refcnt(1) {} // construct an invalid token explicit token_data(int) : id(T_UNKNOWN), refcnt(1) {} token_data(boost::wave::token_id id_, string_type const &value_, position_type const &pos_) : id(id_), value(value_), pos(pos_), corrected_pos(pos_), refcnt(1) {} token_data(token_data const& rhs) : id(rhs.id), value(rhs.value), pos(rhs.pos), corrected_pos(rhs.corrected_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 boost::wave::token_id() const { return id; } string_type const &get_value() const { return value; } position_type const &get_position() const { return pos; } position_type const &get_corrected_position() const { return corrected_pos; } bool is_eoi() const { id == T_EOI; } void set_token_id (boost::wave::token_id id_) { id = id_; } void set_value (string_type const &value_) { value = value_; } void set_position (position_type const &pos_) { pos = pos_; } void set_corrected_position (position_type const &pos_) { corrected_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; } private: boost::wave::token_id id; // the token id string_type value; // the text, which was parsed into this token position_type pos; // the original file position position_type corrected_pos; // the original file position boost::detail::atomic_count refcnt; }; /////////////////////////////////////////////////////////////////////////////// } // namespace impl /////////////////////////////////////////////////////////////////////////////// // forward declaration of the token type template class lex_token; /////////////////////////////////////////////////////////////////////////////// // // lex_token // /////////////////////////////////////////////////////////////////////////////// template class lex_token { public: typedef BOOST_WAVE_STRINGTYPE string_type; typedef PositionT position_type; lex_token() : data(new impl::token_data()) {} // construct an invalid token explicit lex_token(int) : data(new data_type(0)) {} lex_token(lex_token const& rhs) : data(rhs.data) { data->addref(); } lex_token(boost::wave::token_id id_, string_type const &value_, PositionT const &pos_) : data(new impl::token_data(id_, value_, pos_)) {} ~lex_token() { if (0 == data->release()) delete data; data = 0; } lex_token& operator=(lex_token const& rhs) { if (&rhs != this) { if (0 == data->release()) delete data; data = rhs.data; data->addref(); } return *this; } // accessors operator boost::wave::token_id() const { return boost::wave::token_id(*data); } string_type const &get_value() const { return data->get_value(); } position_type const &get_position() const { return data->get_position(); } position_type const &get_corrected_position() const { return data->get_corrected_position(); } bool is_valid() const { return 0 != data && token_id(*data) != T_UNKNOWN; } void set_token_id (boost::wave::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_); } void set_corrected_position (position_type const &pos_) { make_unique(); data->set_corrected_position(pos_); } friend bool operator== (lex_token const& lhs, lex_token const& rhs) { 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 private: // make a unique copy of the current object void make_unique() { if (1 == data->get_refcnt()) return; impl::token_data *newdata = new impl::token_data(*data); data->release(); // release this reference, can't get zero data = newdata; } impl::token_data *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 inline bool token_is_valid(lex_token const& t) { return t.is_valid(); } #endif // !defined(REAL_POSITION_TOKEN_HPP_HK_061109_INCLUDED)