slex_iterator.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. Definition of the lexer iterator
  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(SLEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED)
  10. #define SLEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED
  11. #include <string>
  12. #include <iostream>
  13. #include <boost/assert.hpp>
  14. #include <boost/shared_ptr.hpp>
  15. #include <boost/spirit/include/support_multi_pass.hpp>
  16. #include <boost/wave/language_support.hpp>
  17. #include <boost/wave/util/file_position.hpp>
  18. #include <boost/wave/util/functor_input.hpp>
  19. #include "slex_interface.hpp"
  20. #if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
  21. #define BOOST_WAVE_EOF_PREFIX static
  22. #else
  23. #define BOOST_WAVE_EOF_PREFIX
  24. #endif
  25. ///////////////////////////////////////////////////////////////////////////////
  26. namespace boost {
  27. namespace wave {
  28. namespace cpplexer {
  29. namespace slex {
  30. namespace impl {
  31. ///////////////////////////////////////////////////////////////////////////////
  32. //
  33. // lex_iterator_functor_shim
  34. //
  35. ///////////////////////////////////////////////////////////////////////////////
  36. template <typename TokenT>
  37. class slex_iterator_functor_shim
  38. {
  39. typedef typename TokenT::position_type position_type;
  40. public:
  41. slex_iterator_functor_shim()
  42. #if /*0 != __DECCXX_VER || */defined(__PGI)
  43. : eof()
  44. #endif // 0 != __DECCXX_VER
  45. {}
  46. // interface to the boost::spirit::classic::iterator_policies::functor_input
  47. // policy
  48. typedef TokenT result_type;
  49. typedef slex_iterator_functor_shim unique;
  50. typedef lex_input_interface<TokenT>* shared;
  51. BOOST_WAVE_EOF_PREFIX result_type const eof;
  52. template <typename MultiPass>
  53. static result_type& get_next(MultiPass& mp, result_type& result)
  54. {
  55. return mp.shared()->ftor->get(result);
  56. }
  57. // this will be called whenever the last reference to a multi_pass will
  58. // be released
  59. template <typename MultiPass>
  60. static void destroy(MultiPass& mp)
  61. {
  62. delete mp.shared()->ftor;
  63. }
  64. template <typename MultiPass>
  65. static void set_position(MultiPass& mp, position_type const &pos)
  66. {
  67. mp.shared()->ftor->set_position(pos);
  68. }
  69. #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
  70. template <typename MultiPass>
  71. static bool has_include_guards(MultiPass& mp, std::string& guard_name)
  72. {
  73. return mp.shared()->ftor->has_include_guards(guard_name);
  74. }
  75. #endif
  76. private:
  77. boost::shared_ptr<lex_input_interface<TokenT> > functor_ptr;
  78. };
  79. #if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
  80. ///////////////////////////////////////////////////////////////////////////////
  81. // eof token
  82. template <typename TokenT>
  83. typename slex_iterator_functor_shim<TokenT>::result_type const
  84. slex_iterator_functor_shim<TokenT>::eof =
  85. typename slex_iterator_functor_shim<TokenT>::result_type();
  86. #endif // 0 != __COMO_VERSION__
  87. ///////////////////////////////////////////////////////////////////////////////
  88. } // namespace impl
  89. ///////////////////////////////////////////////////////////////////////////////
  90. //
  91. // slex_iterator
  92. //
  93. // A generic C++ lexer interface class, which allows to plug in different
  94. // lexer implementations (template parameter LexT). The following
  95. // requirement apply:
  96. //
  97. // - the lexer type should have a function implemented, which returnes
  98. // the next lexed token from the input stream:
  99. // typename LexT::token_type get();
  100. // - at the end of the input stream this function should return the
  101. // eof token equivalent
  102. // - the lexer should implement a constructor taking two iterators
  103. // pointing to the beginning and the end of the input stream and
  104. // a third parameter containing the name of the parsed input file,
  105. // the 4th parameter contains the information about the mode the
  106. // preprocessor is used in (C99/C++ mode etc.)
  107. //
  108. ///////////////////////////////////////////////////////////////////////////////
  109. ///////////////////////////////////////////////////////////////////////////////
  110. // Divide the given functor type into its components (unique and shared)
  111. // and build a std::pair from these parts
  112. template <typename FunctorData>
  113. struct make_multi_pass
  114. {
  115. typedef
  116. std::pair<typename FunctorData::unique, typename FunctorData::shared>
  117. functor_data_type;
  118. typedef typename FunctorData::result_type result_type;
  119. typedef boost::spirit::iterator_policies::split_functor_input input_policy;
  120. typedef boost::spirit::iterator_policies::ref_counted ownership_policy;
  121. #if defined(BOOST_WAVE_DEBUG)
  122. typedef boost::spirit::iterator_policies::buf_id_check check_policy;
  123. #else
  124. typedef boost::spirit::iterator_policies::no_check check_policy;
  125. #endif
  126. typedef boost::spirit::iterator_policies::split_std_deque storage_policy;
  127. typedef boost::spirit::iterator_policies::default_policy<
  128. ownership_policy, check_policy, input_policy, storage_policy>
  129. policy_type;
  130. typedef boost::spirit::multi_pass<functor_data_type, policy_type> type;
  131. };
  132. ///////////////////////////////////////////////////////////////////////////////
  133. template <typename TokenT>
  134. class slex_iterator
  135. : public make_multi_pass<impl::slex_iterator_functor_shim<TokenT> >::type
  136. {
  137. typedef impl::slex_iterator_functor_shim<TokenT> input_policy_type;
  138. typedef typename make_multi_pass<input_policy_type>::type base_type;
  139. typedef typename make_multi_pass<input_policy_type>::functor_data_type
  140. functor_data_type;
  141. typedef typename input_policy_type::unique unique_functor_type;
  142. typedef typename input_policy_type::shared shared_functor_type;
  143. public:
  144. typedef TokenT token_type;
  145. slex_iterator()
  146. {}
  147. template <typename IteratorT>
  148. slex_iterator(IteratorT const &first, IteratorT const &last,
  149. typename TokenT::position_type const &pos,
  150. boost::wave::language_support language)
  151. : base_type(
  152. functor_data_type(
  153. unique_functor_type(),
  154. slex_input_interface<TokenT>
  155. ::new_lexer(first, last, pos, language)
  156. )
  157. )
  158. {}
  159. void set_position(typename TokenT::position_type const &pos)
  160. {
  161. typedef typename token_type::position_type position_type;
  162. // set the new position in the current token
  163. token_type const& currtoken = this->base_type::dereference(*this);
  164. position_type currpos = currtoken.get_position();
  165. currpos.set_file(pos.get_file());
  166. currpos.set_line(pos.get_line());
  167. const_cast<token_type&>(currtoken).set_position(currpos);
  168. // set the new position for future tokens as well
  169. if (token_type::string_type::npos !=
  170. currtoken.get_value().find_first_of('\n'))
  171. {
  172. currpos.set_line(pos.get_line() + 1);
  173. }
  174. unique_functor_type::set_position(*this, currpos);
  175. }
  176. #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
  177. // return, whether the current file has include guards
  178. // this function returns meaningful results only if the file was scanned
  179. // completely
  180. bool has_include_guards(std::string& guard_name) const
  181. {
  182. return unique_functor_type::has_include_guards(*this, guard_name);
  183. }
  184. #endif
  185. };
  186. ///////////////////////////////////////////////////////////////////////////////
  187. } // slex
  188. } // namespace cpplexer
  189. } // namespace wave
  190. } // namespace boost
  191. #undef BOOST_WAVE_EOF_PREFIX
  192. #endif // !defined(SLEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED)