as_set.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // as_set.hpp
  3. //
  4. // Copyright 2008 Eric Niebler. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_SET_HPP_EAN_04_05_2007
  8. #define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_SET_HPP_EAN_04_05_2007
  9. // MS compatible compilers support #pragma once
  10. #if defined(_MSC_VER)
  11. # pragma once
  12. #endif
  13. #include <boost/mpl/assert.hpp>
  14. #include <boost/proto/core.hpp>
  15. #include <boost/xpressive/detail/detail_fwd.hpp>
  16. #include <boost/xpressive/detail/static/static.hpp>
  17. #include <boost/xpressive/detail/utility/chset/chset.hpp>
  18. #include <boost/xpressive/detail/utility/traits_utils.hpp>
  19. namespace boost { namespace xpressive { namespace grammar_detail
  20. {
  21. ///////////////////////////////////////////////////////////////////////////
  22. // CharLiteral
  23. template<typename Char>
  24. struct CharLiteral
  25. : or_<
  26. terminal<char>
  27. , terminal<Char>
  28. >
  29. {};
  30. template<>
  31. struct CharLiteral<char>
  32. : terminal<char>
  33. {};
  34. ///////////////////////////////////////////////////////////////////////////
  35. // ListSet
  36. // matches expressions like (set= 'a','b','c')
  37. // calculates the size of the set
  38. template<typename Char>
  39. struct ListSet
  40. : or_<
  41. when<
  42. comma<ListSet<Char>, CharLiteral<Char> >
  43. , make<mpl::next<call<ListSet<Char>(_left)> > > // TODO make a custom transform for this...
  44. >
  45. , when<
  46. assign<detail::set_initializer_type, CharLiteral<Char> >
  47. , make<mpl::int_<1> >
  48. >
  49. >
  50. {};
  51. template<typename Char, typename Traits>
  52. void fill_list_set(Char *&, detail::set_initializer_type, Traits const &)
  53. {}
  54. template<typename Char, typename Expr, typename Traits>
  55. void fill_list_set(Char *&buffer, Expr const &expr, Traits const &traits)
  56. {
  57. fill_list_set(buffer, proto::left(expr), traits);
  58. *buffer++ = traits.translate(detail::char_cast<Char>(proto::value(proto::right(expr)), traits));
  59. }
  60. ///////////////////////////////////////////////////////////////////////////////
  61. // as_list_set_matcher
  62. template<typename Char, typename Callable = proto::callable>
  63. struct as_list_set_matcher : proto::transform<as_list_set_matcher<Char, Callable> >
  64. {
  65. template<typename Expr, typename State, typename Data>
  66. struct impl : proto::transform_impl<Expr, State, Data>
  67. {
  68. typedef typename impl::data data_type;
  69. typedef
  70. detail::set_matcher<
  71. typename data_type::traits_type
  72. , typename ListSet<Char>::template impl<Expr, State, Data>::result_type
  73. >
  74. result_type;
  75. result_type operator ()(
  76. typename impl::expr_param expr
  77. , typename impl::state_param
  78. , typename impl::data_param data
  79. ) const
  80. {
  81. result_type set;
  82. typedef typename impl::data data_type;
  83. typename data_type::char_type *buffer = set.set_;
  84. fill_list_set(buffer, expr, data.traits());
  85. return set;
  86. }
  87. };
  88. };
  89. ///////////////////////////////////////////////////////////////////////////////
  90. // merge_charset
  91. //
  92. template<typename Grammar, typename CharSet, typename Data>
  93. struct merge_charset
  94. {
  95. typedef typename Data::traits_type traits_type;
  96. typedef typename CharSet::char_type char_type;
  97. typedef typename CharSet::icase_type icase_type;
  98. merge_charset(CharSet &charset, Data &data)
  99. : charset_(charset)
  100. , visitor_(data)
  101. {}
  102. template<typename Expr>
  103. void operator ()(Expr const &expr) const
  104. {
  105. this->call_(expr, typename Expr::proto_tag());
  106. }
  107. private:
  108. merge_charset &operator =(merge_charset const &);
  109. template<typename Expr, typename Tag>
  110. void call_(Expr const &expr, Tag) const
  111. {
  112. this->set_(
  113. typename Grammar::template impl<Expr const &, detail::end_xpression, Data &>()(
  114. expr
  115. , detail::end_xpression()
  116. , this->visitor_
  117. )
  118. );
  119. }
  120. template<typename Expr>
  121. void call_(Expr const &expr, tag::bitwise_or) const
  122. {
  123. (*this)(proto::left(expr));
  124. (*this)(proto::right(expr));
  125. }
  126. template<typename Not>
  127. void set_(detail::literal_matcher<traits_type, icase_type, Not> const &ch) const
  128. {
  129. // BUGBUG fixme!
  130. BOOST_MPL_ASSERT_NOT((Not));
  131. set_char(this->charset_.charset_, ch.ch_, this->visitor_.traits(), icase_type());
  132. }
  133. void set_(detail::range_matcher<traits_type, icase_type> const &rg) const
  134. {
  135. // BUGBUG fixme!
  136. BOOST_ASSERT(!rg.not_);
  137. set_range(this->charset_.charset_, rg.ch_min_, rg.ch_max_, this->visitor_.traits(), icase_type());
  138. }
  139. template<typename Size>
  140. void set_(detail::set_matcher<traits_type, Size> const &set_) const
  141. {
  142. // BUGBUG fixme!
  143. BOOST_ASSERT(!set_.not_);
  144. for(int i = 0; i < Size::value; ++i)
  145. {
  146. set_char(this->charset_.charset_, set_.set_[i], this->visitor_.traits(), icase_type());
  147. }
  148. }
  149. void set_(detail::posix_charset_matcher<traits_type> const &posix) const
  150. {
  151. set_class(this->charset_.charset_, posix.mask_, posix.not_, this->visitor_.traits());
  152. }
  153. CharSet &charset_;
  154. Data &visitor_;
  155. };
  156. ///////////////////////////////////////////////////////////////////////////////
  157. //
  158. template<typename Grammar, typename Callable = proto::callable>
  159. struct as_set_matcher : proto::transform<as_set_matcher<Grammar, Callable> >
  160. {
  161. template<typename Expr, typename State, typename Data>
  162. struct impl : proto::transform_impl<Expr, State, Data>
  163. {
  164. typedef typename impl::data data_type;
  165. typedef typename data_type::char_type char_type;
  166. // if sizeof(char_type)==1, merge everything into a basic_chset
  167. // BUGBUG this is not optimal.
  168. typedef
  169. typename mpl::if_c<
  170. detail::is_narrow_char<char_type>::value
  171. , detail::basic_chset<char_type>
  172. , detail::compound_charset<typename data_type::traits_type>
  173. >::type
  174. charset_type;
  175. typedef
  176. detail::charset_matcher<
  177. typename data_type::traits_type
  178. , typename data_type::icase_type
  179. , charset_type
  180. >
  181. result_type;
  182. result_type operator ()(
  183. typename impl::expr_param expr
  184. , typename impl::state_param
  185. , typename impl::data_param data
  186. ) const
  187. {
  188. result_type matcher;
  189. merge_charset<Grammar, result_type, typename impl::data> merge(matcher, data);
  190. merge(expr); // Walks the tree and fills in the charset
  191. return matcher;
  192. }
  193. };
  194. };
  195. }}}
  196. #endif