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