cpp_lex_token.hpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. A generic C++ lexer token definition
  4. http://www.boost.org/
  5. Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
  6. Software License, Version 1.0. (See accompanying file
  7. LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. =============================================================================*/
  9. #if !defined(CPP_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED)
  10. #define CPP_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED
  11. #include <boost/wave/wave_config.hpp>
  12. #if BOOST_WAVE_SERIALIZATION != 0
  13. #include <boost/serialization/serialization.hpp>
  14. #endif
  15. #include <boost/wave/util/file_position.hpp>
  16. #include <boost/wave/token_ids.hpp>
  17. #include <boost/wave/language_support.hpp>
  18. #include <boost/throw_exception.hpp>
  19. #include <boost/pool/singleton_pool.hpp>
  20. #include <boost/detail/atomic_count.hpp>
  21. // this must occur after all of the includes and before any code appears
  22. #ifdef BOOST_HAS_ABI_HEADERS
  23. #include BOOST_ABI_PREFIX
  24. #endif
  25. ///////////////////////////////////////////////////////////////////////////////
  26. namespace boost {
  27. namespace wave {
  28. namespace cpplexer {
  29. namespace impl {
  30. template <typename StringTypeT, typename PositionT>
  31. class token_data
  32. {
  33. public:
  34. typedef StringTypeT string_type;
  35. typedef PositionT position_type;
  36. // default constructed tokens correspond to EOI tokens
  37. token_data()
  38. : id(T_EOI), refcnt(1)
  39. {}
  40. // construct an invalid token
  41. explicit token_data(int)
  42. : id(T_UNKNOWN), refcnt(1)
  43. {}
  44. token_data(token_id id_, string_type const &value_, position_type const &pos_)
  45. : id(id_), value(value_), pos(pos_), refcnt(1)
  46. {}
  47. token_data(token_data const& rhs)
  48. : id(rhs.id), value(rhs.value), pos(rhs.pos), refcnt(1)
  49. {}
  50. ~token_data()
  51. {}
  52. std::size_t addref() { return ++refcnt; }
  53. std::size_t release() { return --refcnt; }
  54. std::size_t get_refcnt() const { return refcnt; }
  55. // accessors
  56. operator token_id() const { return id; }
  57. string_type const &get_value() const { return value; }
  58. position_type const &get_position() const { return pos; }
  59. void set_token_id (token_id id_) { id = id_; }
  60. void set_value (string_type const &value_) { value = value_; }
  61. void set_position (position_type const &pos_) { pos = pos_; }
  62. friend bool operator== (token_data const& lhs, token_data const& rhs)
  63. {
  64. // two tokens are considered equal even if they refer to different
  65. // positions
  66. return (lhs.id == rhs.id && lhs.value == rhs.value) ? true : false;
  67. }
  68. void init(token_id id_, string_type const &value_, position_type const &pos_)
  69. {
  70. BOOST_ASSERT(refcnt == 1);
  71. id = id_;
  72. value = value_;
  73. pos = pos_;
  74. }
  75. void init(token_data const& rhs)
  76. {
  77. BOOST_ASSERT(refcnt == 1);
  78. id = rhs.id;
  79. value = rhs.value;
  80. pos = rhs.pos;
  81. }
  82. static void *operator new(std::size_t size);
  83. static void operator delete(void *p, std::size_t size);
  84. #if defined(BOOST_SPIRIT_DEBUG)
  85. // debug support
  86. void print (std::ostream &stream) const
  87. {
  88. stream << get_token_name(id) << "(";
  89. for (std::size_t i = 0; i < value.size(); ++i) {
  90. switch (value[i]) {
  91. case '\r': stream << "\\r"; break;
  92. case '\n': stream << "\\n"; break;
  93. default:
  94. stream << value[i];
  95. break;
  96. }
  97. }
  98. stream << ")";
  99. }
  100. #endif // defined(BOOST_SPIRIT_DEBUG)
  101. #if BOOST_WAVE_SERIALIZATION != 0
  102. friend class boost::serialization::access;
  103. template<typename Archive>
  104. void serialize(Archive &ar, const unsigned int version)
  105. {
  106. using namespace boost::serialization;
  107. ar & make_nvp("id", id);
  108. ar & make_nvp("value", value);
  109. ar & make_nvp("position", pos);
  110. }
  111. #endif
  112. private:
  113. token_id id; // the token id
  114. string_type value; // the text, which was parsed into this token
  115. position_type pos; // the original file position
  116. boost::detail::atomic_count refcnt;
  117. };
  118. ///////////////////////////////////////////////////////////////////////////////
  119. struct token_data_tag {};
  120. template <typename StringTypeT, typename PositionT>
  121. inline void *
  122. token_data<StringTypeT, PositionT>::operator new(std::size_t size)
  123. {
  124. BOOST_ASSERT(sizeof(token_data<StringTypeT, PositionT>) == size);
  125. typedef boost::singleton_pool<
  126. token_data_tag, sizeof(token_data<StringTypeT, PositionT>)
  127. > pool_type;
  128. void *ret = pool_type::malloc();
  129. if (0 == ret)
  130. boost::throw_exception(std::bad_alloc());
  131. return ret;
  132. }
  133. template <typename StringTypeT, typename PositionT>
  134. inline void
  135. token_data<StringTypeT, PositionT>::operator delete(void *p, std::size_t size)
  136. {
  137. BOOST_ASSERT(sizeof(token_data<StringTypeT, PositionT>) == size);
  138. typedef boost::singleton_pool<
  139. token_data_tag, sizeof(token_data<StringTypeT, PositionT>)
  140. > pool_type;
  141. if (0 != p)
  142. pool_type::free(p);
  143. }
  144. } // namespace impl
  145. ///////////////////////////////////////////////////////////////////////////////
  146. // forward declaration of the token type
  147. template <typename PositionT = boost::wave::util::file_position_type>
  148. class lex_token;
  149. ///////////////////////////////////////////////////////////////////////////////
  150. //
  151. // lex_token
  152. //
  153. ///////////////////////////////////////////////////////////////////////////////
  154. template <typename PositionT>
  155. class lex_token
  156. {
  157. public:
  158. typedef BOOST_WAVE_STRINGTYPE string_type;
  159. typedef PositionT position_type;
  160. private:
  161. typedef impl::token_data<string_type, position_type> data_type;
  162. public:
  163. // default constructed tokens correspond to EOI tokens
  164. lex_token()
  165. : data(0)
  166. {}
  167. // construct an invalid token
  168. explicit lex_token(int)
  169. : data(new data_type(0))
  170. {}
  171. lex_token(lex_token const& rhs)
  172. : data(rhs.data)
  173. {
  174. if (0 != data)
  175. data->addref();
  176. }
  177. lex_token(token_id id_, string_type const &value_, PositionT const &pos_)
  178. : data(new data_type(id_, value_, pos_))
  179. {}
  180. ~lex_token()
  181. {
  182. if (0 != data && 0 == data->release())
  183. delete data;
  184. data = 0;
  185. }
  186. lex_token& operator=(lex_token const& rhs)
  187. {
  188. if (&rhs != this) {
  189. if (0 != data && 0 == data->release())
  190. delete data;
  191. data = rhs.data;
  192. if (0 != data)
  193. data->addref();
  194. }
  195. return *this;
  196. }
  197. // accessors
  198. operator token_id() const { return 0 != data ? token_id(*data) : T_EOI; }
  199. string_type const &get_value() const { return data->get_value(); }
  200. position_type const &get_position() const { return data->get_position(); }
  201. bool is_eoi() const { return 0 == data || token_id(*data) == T_EOI; }
  202. bool is_valid() const { return 0 != data && token_id(*data) != T_UNKNOWN; }
  203. void set_token_id (token_id id_) { make_unique(); data->set_token_id(id_); }
  204. void set_value (string_type const &value_) { make_unique(); data->set_value(value_); }
  205. void set_position (position_type const &pos_) { make_unique(); data->set_position(pos_); }
  206. friend bool operator== (lex_token const& lhs, lex_token const& rhs)
  207. {
  208. if (0 == rhs.data)
  209. return 0 == lhs.data;
  210. if (0 == lhs.data)
  211. return false;
  212. return *(lhs.data) == *(rhs.data);
  213. }
  214. // debug support
  215. #if BOOST_WAVE_DUMP_PARSE_TREE != 0
  216. // access functions for the tree_to_xml functionality
  217. static int get_token_id(lex_token const &t)
  218. { return token_id(t); }
  219. static string_type get_token_value(lex_token const &t)
  220. { return t.get_value(); }
  221. #endif
  222. #if defined(BOOST_SPIRIT_DEBUG)
  223. // debug support
  224. void print (std::ostream &stream) const
  225. {
  226. data->print(stream);
  227. }
  228. #endif // defined(BOOST_SPIRIT_DEBUG)
  229. private:
  230. #if BOOST_WAVE_SERIALIZATION != 0
  231. friend class boost::serialization::access;
  232. template<typename Archive>
  233. void serialize(Archive &ar, const unsigned int version)
  234. {
  235. data->serialize(ar, version);
  236. }
  237. #endif
  238. // make a unique copy of the current object
  239. void make_unique()
  240. {
  241. if (1 == data->get_refcnt())
  242. return;
  243. data_type* newdata = new data_type(*data) ;
  244. data->release(); // release this reference, can't get zero
  245. data = newdata;
  246. }
  247. data_type* data;
  248. };
  249. ///////////////////////////////////////////////////////////////////////////////
  250. // This overload is needed by the multi_pass/functor_input_policy to
  251. // validate a token instance. It has to be defined in the same namespace
  252. // as the token class itself to allow ADL to find it.
  253. ///////////////////////////////////////////////////////////////////////////////
  254. template <typename Position>
  255. inline bool
  256. token_is_valid(lex_token<Position> const& t)
  257. {
  258. return t.is_valid();
  259. }
  260. ///////////////////////////////////////////////////////////////////////////////
  261. #if defined(BOOST_SPIRIT_DEBUG)
  262. template <typename PositionT>
  263. inline std::ostream &
  264. operator<< (std::ostream &stream, lex_token<PositionT> const &object)
  265. {
  266. object.print(stream);
  267. return stream;
  268. }
  269. #endif // defined(BOOST_SPIRIT_DEBUG)
  270. ///////////////////////////////////////////////////////////////////////////////
  271. } // namespace cpplexer
  272. } // namespace wave
  273. } // namespace boost
  274. // the suffix header occurs after all of the code
  275. #ifdef BOOST_HAS_ABI_HEADERS
  276. #include BOOST_ABI_SUFFIX
  277. #endif
  278. #endif // !defined(CPP_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED)