1 /*=============================================================================
2     Copyright (c) 2005-2010 Joel de Guzman
3     Copyright (c) 2010 Eric Niebler
4     Copyright (c) 2010 Thomas Heller
5 
6     Distributed under the Boost Software License, Version 1.0. (See accompanying
7     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 ==============================================================================*/
9 #ifndef BOOST_PHOENIX_CORE_META_GRAMMAR_HPP
10 #define BOOST_PHOENIX_CORE_META_GRAMMAR_HPP
11 
12 #include <boost/phoenix/core/limits.hpp>
13 #include <boost/mpl/deref.hpp>
14 #include <boost/phoenix/core/environment.hpp>
15 #include <boost/proto/matches.hpp>
16 #include <boost/proto/transform/call.hpp>
17 #include <boost/proto/transform/default.hpp>
18 
19 namespace boost { namespace phoenix
20 {
21     /////////////////////////////////////////////////////////////////////////////
22     // The grammar defining valid phoenix expressions
23     struct meta_grammar
24         : proto::switch_<meta_grammar>
25     {
26         template <typename Tag, typename Dummy = void>
27         struct case_
28             : proto::not_<proto::_>
29         {};
30     };
31 
32     struct evaluator
33     {
34         BOOST_PROTO_TRANSFORM(evaluator)
35 
36         template <typename Expr, typename State, typename Data>
37         struct impl
38             : proto::transform_impl<Expr, State, Data>
39         {
40             typedef meta_grammar::impl<Expr, State, Data> what;
41 
42             typedef typename what::result_type result_type;
43 
operator ()boost::phoenix::evaluator::impl44             result_type operator()(
45                 typename impl::expr_param e
46               , typename impl::state_param s
47               , typename impl::data_param d
48             ) const
49             {
50                 return what()(e, s, d);
51             }
52         };
53 
54         template <typename Expr, typename State>
55         struct impl<Expr, State, proto::empty_env>
56             : proto::transform_impl<Expr, State, proto::empty_env>
57         {
58             typedef
59                 meta_grammar::impl<
60                     Expr
61                   , typename result_of::env<State>::type
62                   , typename result_of::actions<State>::type
63                 >
64                 what;
65 
66             typedef typename what::result_type result_type;
67 
operator ()boost::phoenix::evaluator::impl68             result_type operator()(
69                 typename impl::expr_param e
70               , typename impl::state_param s
71               , typename impl::data_param
72             ) const
73             {
74                 return what()(e, phoenix::env(s), actions(s));
75             }
76         };
77 
78         template <typename Expr, typename State>
79         struct impl<Expr, State, unused>
80             : proto::transform_impl<Expr, State, unused>
81         {
82             typedef
83                 meta_grammar::impl<
84                     Expr
85                   , typename result_of::env<State>::type
86                   , typename result_of::actions<State>::type
87                 >
88                 what;
89 
90             typedef typename what::result_type result_type;
91 
operator ()boost::phoenix::evaluator::impl92             result_type operator()(
93                 typename impl::expr_param e
94               , typename impl::state_param s
95               , typename impl::data_param
96             ) const
97             {
98                 return what()(e, phoenix::env(s), actions(s));
99             }
100         };
101     };
102 
103     /////////////////////////////////////////////////////////////////////////////
104     // Set of default actions. Extend this whenever you add a new phoenix
105     // construct
106     struct default_actions
107     {
108         template <typename Rule, typename Dummy = void>
109         struct when
110             : proto::_default<meta_grammar>
111         {};
112     };
113 
114     template <typename Rule, typename Dummy = void>
115     struct enable_rule
116         : proto::when<Rule, proto::external_transform>
117     {};
118 
119     namespace result_of
120     {
121         template <typename Expr, typename Context>
122         struct eval
123             : boost::result_of< ::boost::phoenix::evaluator(Expr, Context)>
124         {};
125     }
126 
127     /////////////////////////////////////////////////////////////////////////////
128     // A function we can call to evaluate our expression
129     template <typename Expr, typename Context>
130     inline
131     typename meta_grammar::template impl<
132         Expr const&
133       , typename result_of::env<Context const&>::type
134       , typename result_of::actions<Context const&>::type
135     >::result_type
eval(Expr const & expr,Context const & ctx)136     eval(Expr const& expr, Context const & ctx)
137     {
138         static evaluator const e = {};
139         return e(expr, ctx);
140     }
141 
142     template <typename Expr, typename Context>
143     inline
144     typename meta_grammar::template impl<
145         Expr &
146       , typename result_of::env<Context const&>::type
147       , typename result_of::actions<Context const&>::type
148     >::result_type
eval(Expr & expr,Context const & ctx)149     eval(Expr & expr, Context const & ctx)
150     {
151         static evaluator const e = {};
152         return e(expr, ctx);
153     }
154 }}
155 
156 #endif
157