1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3
4 A C++ lexer token definition for the real_positions example
5
6 http://www.boost.org/
7
8 Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost
9 Software License, Version 1.0. (See accompanying file
10 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 =============================================================================*/
12
13 #if !defined(REAL_POSITION_TOKEN_HPP_HK_061109_INCLUDED)
14 #define REAL_POSITION_TOKEN_HPP_HK_061109_INCLUDED
15
16 #include <boost/wave/wave_config.hpp>
17 #include <boost/wave/util/file_position.hpp>
18 #include <boost/wave/token_ids.hpp>
19 #include <boost/wave/language_support.hpp>
20 #include <boost/detail/atomic_count.hpp>
21
22 ///////////////////////////////////////////////////////////////////////////////
23 namespace impl {
24
25 template <typename StringTypeT, typename PositionT>
26 class token_data
27 {
28 public:
29 typedef StringTypeT string_type;
30 typedef PositionT position_type;
31
token_data()32 token_data()
33 : id(boost::wave::T_EOI), refcnt(1)
34 {}
35
36 // construct an invalid token
token_data(int)37 explicit token_data(int)
38 : id(T_UNKNOWN), refcnt(1)
39 {}
40
token_data(boost::wave::token_id id_,string_type const & value_,position_type const & pos_)41 token_data(boost::wave::token_id id_, string_type const &value_,
42 position_type const &pos_)
43 : id(id_), value(value_), pos(pos_), corrected_pos(pos_), refcnt(1)
44 {}
45
token_data(token_data const & rhs)46 token_data(token_data const& rhs)
47 : id(rhs.id), value(rhs.value), pos(rhs.pos),
48 corrected_pos(rhs.corrected_pos), refcnt(1)
49 {}
50
~token_data()51 ~token_data()
52 {}
53
addref()54 std::size_t addref() { return ++refcnt; }
release()55 std::size_t release() { return --refcnt; }
get_refcnt() const56 std::size_t get_refcnt() const { return refcnt; }
57
58 // accessors
operator boost::wave::token_id() const59 operator boost::wave::token_id() const { return id; }
get_value() const60 string_type const &get_value() const { return value; }
get_position() const61 position_type const &get_position() const { return pos; }
get_corrected_position() const62 position_type const &get_corrected_position() const
63 { return corrected_pos; }
is_eoi() const64 bool is_eoi() const { id == T_EOI; }
65
set_token_id(boost::wave::token_id id_)66 void set_token_id (boost::wave::token_id id_) { id = id_; }
set_value(string_type const & value_)67 void set_value (string_type const &value_) { value = value_; }
set_position(position_type const & pos_)68 void set_position (position_type const &pos_) { pos = pos_; }
set_corrected_position(position_type const & pos_)69 void set_corrected_position (position_type const &pos_)
70 { corrected_pos = pos_; }
71
operator ==(token_data const & lhs,token_data const & rhs)72 friend bool operator== (token_data const& lhs, token_data const& rhs)
73 {
74 // two tokens are considered equal even if they refer to different
75 // positions
76 return (lhs.id == rhs.id && lhs.value == rhs.value) ? true : false;
77 }
78
79 private:
80 boost::wave::token_id id; // the token id
81 string_type value; // the text, which was parsed into this token
82 position_type pos; // the original file position
83 position_type corrected_pos; // the original file position
84 boost::detail::atomic_count refcnt;
85 };
86
87 ///////////////////////////////////////////////////////////////////////////////
88 } // namespace impl
89
90 ///////////////////////////////////////////////////////////////////////////////
91 // forward declaration of the token type
92 template <typename PositionT = boost::wave::util::file_position_type>
93 class lex_token;
94
95 ///////////////////////////////////////////////////////////////////////////////
96 //
97 // lex_token
98 //
99 ///////////////////////////////////////////////////////////////////////////////
100
101 template <typename PositionT>
102 class lex_token
103 {
104 public:
105 typedef BOOST_WAVE_STRINGTYPE string_type;
106 typedef PositionT position_type;
107
lex_token()108 lex_token()
109 : data(new impl::token_data<string_type, position_type>())
110 {}
111
112 // construct an invalid token
lex_token(int)113 explicit lex_token(int)
114 : data(new data_type(0))
115 {}
116
lex_token(lex_token const & rhs)117 lex_token(lex_token const& rhs)
118 : data(rhs.data)
119 {
120 data->addref();
121 }
122
lex_token(boost::wave::token_id id_,string_type const & value_,PositionT const & pos_)123 lex_token(boost::wave::token_id id_, string_type const &value_,
124 PositionT const &pos_)
125 : data(new impl::token_data<string_type, position_type>(id_, value_, pos_))
126 {}
127
~lex_token()128 ~lex_token()
129 {
130 if (0 == data->release())
131 delete data;
132 data = 0;
133 }
134
operator =(lex_token const & rhs)135 lex_token& operator=(lex_token const& rhs)
136 {
137 if (&rhs != this) {
138 if (0 == data->release())
139 delete data;
140
141 data = rhs.data;
142 data->addref();
143 }
144 return *this;
145 }
146
147 // accessors
operator boost::wave::token_id() const148 operator boost::wave::token_id() const
149 { return boost::wave::token_id(*data); }
get_value() const150 string_type const &get_value() const
151 { return data->get_value(); }
get_position() const152 position_type const &get_position() const
153 { return data->get_position(); }
get_corrected_position() const154 position_type const &get_corrected_position() const
155 { return data->get_corrected_position(); }
is_valid() const156 bool is_valid() const { return 0 != data && token_id(*data) != T_UNKNOWN; }
157
set_token_id(boost::wave::token_id id_)158 void set_token_id (boost::wave::token_id id_)
159 { make_unique(); data->set_token_id(id_); }
set_value(string_type const & value_)160 void set_value (string_type const &value_)
161 { make_unique(); data->set_value(value_); }
set_position(position_type const & pos_)162 void set_position (position_type const &pos_)
163 { make_unique(); data->set_position(pos_); }
set_corrected_position(position_type const & pos_)164 void set_corrected_position (position_type const &pos_)
165 { make_unique(); data->set_corrected_position(pos_); }
166
operator ==(lex_token const & lhs,lex_token const & rhs)167 friend bool operator== (lex_token const& lhs, lex_token const& rhs)
168 {
169 return *(lhs.data) == *(rhs.data);
170 }
171
172 // debug support
173 #if BOOST_WAVE_DUMP_PARSE_TREE != 0
174 // access functions for the tree_to_xml functionality
get_token_id(lex_token const & t)175 static int get_token_id(lex_token const &t)
176 { return token_id(t); }
get_token_value(lex_token const & t)177 static string_type get_token_value(lex_token const &t)
178 { return t.get_value(); }
179 #endif
180
181 private:
182 // make a unique copy of the current object
make_unique()183 void make_unique()
184 {
185 if (1 == data->get_refcnt())
186 return;
187
188 impl::token_data<string_type, position_type> *newdata =
189 new impl::token_data<string_type, position_type>(*data);
190
191 data->release(); // release this reference, can't get zero
192 data = newdata;
193 }
194
195 impl::token_data<string_type, position_type> *data;
196 };
197
198 ///////////////////////////////////////////////////////////////////////////////
199 // This overload is needed by the multi_pass/functor_input_policy to
200 // validate a token instance. It has to be defined in the same namespace
201 // as the token class itself to allow ADL to find it.
202 ///////////////////////////////////////////////////////////////////////////////
203 template <typename Position>
204 inline bool
token_is_valid(lex_token<Position> const & t)205 token_is_valid(lex_token<Position> const& t)
206 {
207 return t.is_valid();
208 }
209
210 #endif // !defined(REAL_POSITION_TOKEN_HPP_HK_061109_INCLUDED)
211