terminal.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*==============================================================================
  2. Copyright (c) 2005-2010 Joel de Guzman
  3. Copyright (c) 2010 Thomas Heller
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #ifndef BOOST_PHOENIX_CORE_TERMINAL_HPP
  8. #define BOOST_PHOENIX_CORE_TERMINAL_HPP
  9. #include <boost/phoenix/core/limits.hpp>
  10. #include <boost/is_placeholder.hpp>
  11. #include <boost/phoenix/core/actor.hpp>
  12. #include <boost/phoenix/core/meta_grammar.hpp>
  13. #include <boost/phoenix/core/terminal_fwd.hpp>
  14. #include <boost/proto/matches.hpp>
  15. #include <boost/proto/transform/lazy.hpp>
  16. #include <boost/proto/functional/fusion/at.hpp>
  17. #include <boost/type_traits/remove_pointer.hpp>
  18. #define BOOST_PHOENIX_DEFINE_CUSTOM_TERMINAL(Template, Terminal, IsNullary, EvalFun)\
  19. namespace boost { namespace phoenix \
  20. { \
  21. namespace result_of \
  22. { \
  23. Template \
  24. struct is_nullary< \
  25. custom_terminal< \
  26. Terminal \
  27. > \
  28. > \
  29. : IsNullary \
  30. {}; \
  31. } \
  32. Template \
  33. struct is_custom_terminal<Terminal >: mpl::true_ {}; \
  34. \
  35. Template \
  36. struct custom_terminal<Terminal > : proto::call<EvalFun > {}; \
  37. }} \
  38. /**/
  39. namespace boost { namespace phoenix
  40. {
  41. template <typename T, typename Dummy>
  42. struct is_custom_terminal
  43. : mpl::false_ {};
  44. template <typename T, typename Dummy>
  45. struct custom_terminal;
  46. namespace tag {
  47. struct terminal /*: public proto::tag::terminal */ {};
  48. }
  49. namespace expression
  50. {
  51. template <typename T, template <typename> class Actor = actor>
  52. struct terminal
  53. : proto::terminal<T>
  54. {
  55. typedef
  56. proto::basic_expr<
  57. proto::tag::terminal
  58. // tag::terminal //cannot change to use phoenix tag - breaks code.
  59. , proto::term<T>
  60. , 0
  61. >
  62. base_type;
  63. typedef Actor<base_type> type;
  64. static const type make(T const& t)
  65. {
  66. // ?? Should the next line be Actor not actor which is the default?
  67. actor<base_type> const e = {base_type::make(t)};
  68. //Actor<base_type> const e = {base_type::make(t)};
  69. return e;
  70. }
  71. };
  72. }
  73. namespace rule
  74. {
  75. struct argument
  76. : proto::if_<boost::is_placeholder<proto::_value>()>
  77. {};
  78. struct custom_terminal
  79. : proto::if_<boost::phoenix::is_custom_terminal<proto::_value>()>
  80. {};
  81. struct terminal
  82. : proto::terminal<proto::_>
  83. {};
  84. }
  85. template <typename Dummy>
  86. struct meta_grammar::case_<proto::tag::terminal, Dummy>
  87. : proto::or_<
  88. enable_rule<rule::argument , Dummy>
  89. , enable_rule<rule::custom_terminal, Dummy>
  90. , enable_rule<rule::terminal , Dummy>
  91. >
  92. {};
  93. template <typename Dummy>
  94. struct default_actions::when<rule::custom_terminal, Dummy>
  95. : proto::lazy<
  96. custom_terminal<proto::_value>(
  97. proto::_value
  98. , _context
  99. )
  100. >
  101. {};
  102. namespace detail
  103. {
  104. template <typename N>
  105. struct placeholder_idx
  106. : mpl::int_<N::value>
  107. {};
  108. }
  109. template <typename Grammar>
  110. struct default_actions::when<rule::argument, Grammar>
  111. : proto::call<
  112. proto::functional::at(
  113. _env
  114. , proto::make<
  115. detail::placeholder_idx<
  116. proto::make<
  117. boost::is_placeholder<proto::_value>()
  118. >
  119. >()
  120. >
  121. )
  122. >
  123. {};
  124. }}
  125. #endif