cpp_lex_token.hpp 10 KB

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