1 /*=============================================================================
2     Copyright (c) 2002-2003 Joel de Guzman
3     Copyright (c) 2002-2003 Hartmut Kaiser
4     http://spirit.sourceforge.net/
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 #if !defined(BOOST_SPIRIT_TRAVERSE_HPP)
10 #define BOOST_SPIRIT_TRAVERSE_HPP
11 
12 #include <boost/spirit/home/classic/namespace.hpp>
13 #include <boost/spirit/home/classic/meta/impl/traverse.ipp>
14 
15 namespace boost { namespace spirit {
16 
17 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
18 
19     ///////////////////////////////////////////////////////////////////////////
20     //
21     //  Post-order traversal of auxiliary parsers.
22     //
23     ///////////////////////////////////////////////////////////////////////////
24     struct post_order
25     {
26         //  Return the parser type, which is generated as the result of the
27         //  traverse function below.
28 
29         template <typename MetaT, typename ParserT>
30         struct result
31         {
32             typedef typename
33                 traverse_post_order_return<
34                     MetaT
35                   , ParserT
36                   , traverse_post_order_env<0, 0, 0, 0>
37                 >::type
38             type;
39         };
40 
41         //  Traverse a given parser and refactor it with the help of the given
42         //  MetaT metafunction template.
43 
44         template <typename MetaT, typename ParserT>
45         static typename result<MetaT, ParserT>::type
traverseboost::spirit::post_order46         traverse(MetaT const &meta_, ParserT const &parser_)
47         {
48             typedef typename ParserT::parser_category_t parser_category_t;
49             return impl::traverse_post_order<parser_category_t>::generate(
50                 meta_, parser_, traverse_post_order_env<0, 0, 0, 0>());
51         }
52     };
53 
54     ///////////////////////////////////////////////////////////////////////////
55     //
56     //  Transform policies
57     //
58     //      The following policy classes could be used to assemble some new
59     //      transformation metafunction which uses identity transformations
60     //      for some parser_category type parsers.
61     //
62     ///////////////////////////////////////////////////////////////////////////
63 
64     ///////////////////////////////////////////////////////////////////////////
65     //  transform plain parsers
66     template <typename TransformT>
67     struct plain_identity_policy
68     {
69         template <typename ParserT, typename EnvT>
70         struct plain_result
71         {
72             // plain parsers should be embedded and returned correctly
73             typedef typename ParserT::embed_t type;
74         };
75 
76         template <typename ParserT, typename EnvT>
77         typename parser_traversal_plain_result<TransformT, ParserT, EnvT>::type
generate_plainboost::spirit::plain_identity_policy78         generate_plain(ParserT const &parser_, EnvT const& /*env*/) const
79         {
80             return parser_;
81         }
82     };
83 
84     //////////////////////////////////
85     //  transform unary parsers
86     template <typename UnaryT, typename SubjectT>
87     struct unary_identity_policy_return
88     {
89         typedef typename UnaryT::parser_generator_t parser_generator_t;
90         typedef typename parser_generator_t
91             ::template result<SubjectT>::type type;
92     };
93 
94     template <typename TransformT>
95     struct unary_identity_policy
96     {
97         template <typename UnaryT, typename SubjectT, typename EnvT>
98         struct unary_result
99         {
100             typedef
101                 typename unary_identity_policy_return<UnaryT, SubjectT>::type
102             type;
103         };
104 
105         template <typename UnaryT, typename SubjectT, typename EnvT>
106         typename parser_traversal_unary_result<
107             TransformT, UnaryT, SubjectT, EnvT>::type
generate_unaryboost::spirit::unary_identity_policy108         generate_unary(
109             UnaryT const &, SubjectT const &subject_, EnvT const& /*env*/) const
110         {
111             typedef typename UnaryT::parser_generator_t parser_generator_t;
112             return parser_generator_t::template generate<SubjectT>(subject_);
113         }
114     };
115 
116     //////////////////////////////////
117     //  transform action parsers
118     template <typename TransformT>
119     struct action_identity_policy
120     {
121         template <typename ActionT, typename SubjectT, typename EnvT>
122         struct action_result
123         {
124             typedef action<SubjectT, typename ActionT::predicate_t> type;
125         };
126 
127         template <typename ActionT, typename SubjectT, typename EnvT>
128         typename parser_traversal_action_result<
129             TransformT, ActionT, SubjectT, EnvT
130         >::type
generate_actionboost::spirit::action_identity_policy131         generate_action(ActionT const &action_, SubjectT const &subject_,
132             EnvT const& /*env*/) const
133         {
134             return subject_[action_.predicate()];
135         }
136     };
137 
138     //////////////////////////////////
139     //  transform binary parsers
140     template <typename BinaryT, typename LeftT, typename RightT>
141     struct binary_identity_policy_return
142     {
143         typedef typename BinaryT::parser_generator_t parser_generator_t;
144         typedef typename parser_generator_t
145             ::template result<LeftT, RightT>::type type;
146     };
147 
148     template <typename TransformT>
149     struct binary_identity_policy
150     {
151         template <typename BinaryT, typename LeftT
152             , typename RightT, typename EnvT>
153         struct binary_result {
154 
155             typedef typename
156                 binary_identity_policy_return<BinaryT, LeftT, RightT>::type
157             type;
158         };
159 
160         template <typename BinaryT, typename LeftT
161             , typename RightT, typename EnvT>
162         typename parser_traversal_binary_result<
163             TransformT, BinaryT, LeftT, RightT, EnvT
164         >::type
generate_binaryboost::spirit::binary_identity_policy165         generate_binary(
166             BinaryT const &, LeftT const& left_
167           , RightT const& right_, EnvT const& /*env*/) const
168         {
169             typedef typename BinaryT::parser_generator_t parser_generator_t;
170             return parser_generator_t::
171                 template generate<LeftT, RightT>(left_, right_);
172         }
173     };
174 
175     ///////////////////////////////////////////////////////////////////////////
176     //
177     //  transform_policies template
178     //
179     //      The transform_policies template metafunction could serve as a
180     //      base class for new metafunctions to be passed to the traverse meta
181     //      template (see above), where only minimal parts have to be
182     //      overwritten.
183     //
184     ///////////////////////////////////////////////////////////////////////////
185 
186     template <
187         typename TransformT,
188         typename PlainPolicyT = plain_identity_policy<TransformT>,
189         typename UnaryPolicyT = unary_identity_policy<TransformT>,
190         typename ActionPolicyT = action_identity_policy<TransformT>,
191         typename BinaryPolicyT = binary_identity_policy<TransformT>
192     >
193     struct transform_policies :
194         public PlainPolicyT,
195         public UnaryPolicyT,
196         public ActionPolicyT,
197         public BinaryPolicyT
198     {
199     };
200 
201     ///////////////////////////////////////////////////////////////////////////
202     //
203     //  Identity transformation
204     //
205     //      The identity_transform metafunction supplied to the traverse
206     //      template will generate a new parser, which will be exactly
207     //      identical to the parser given as the parameter to the traverse
208     //      metafunction. I.e. the following conceptual 'equation' will be
209     //      always true:
210     //
211     //      some_parser ==
212     //          post_order::traverse(identity_transform(), some_parser)
213     //
214     ///////////////////////////////////////////////////////////////////////////
215 
216     struct identity_transform : transform_policies<identity_transform> {};
217 
218 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
219 
220 }} // namespace BOOST_SPIRIT_CLASSIC_NS
221 
222 #endif // !defined(BOOST_SPIRIT_TRAVERSE_HPP)
223