source: NonGTP/Boost/boost/spirit/meta/refactoring.hpp @ 857

Revision 857, 9.2 KB checked in by igarcia, 18 years ago (diff)
Line 
1/*=============================================================================
2    Copyright (c) 2002-2003 Hartmut Kaiser
3    http://spirit.sourceforge.net/
4
5    Use, modification and distribution is subject to the Boost Software
6    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7    http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9#ifndef BOOST_SPIRIT_REFACTORING_HPP
10#define BOOST_SPIRIT_REFACTORING_HPP
11
12///////////////////////////////////////////////////////////////////////////////
13#include <boost/static_assert.hpp>
14#include <boost/spirit/meta/as_parser.hpp>
15#include <boost/spirit/core/parser.hpp>
16#include <boost/spirit/core/composite/composite.hpp>
17#include <boost/spirit/meta/impl/refactoring.ipp>
18
19///////////////////////////////////////////////////////////////////////////////
20namespace boost { namespace spirit {
21
22///////////////////////////////////////////////////////////////////////////////
23//
24//  refactor_unary_parser class
25//
26//      This helper template allows to attach an unary operation to a newly
27//      constructed parser, which combines the subject of the left operand of
28//      the original given parser (BinaryT) with the right operand of the
29//      original binary parser through the original binary operation and
30//      rewraps the resulting parser with the original unary operator.
31//
32//      For instance given the parser:
33//          *some_parser - another_parser
34//
35//      will be refactored to:
36//          *(some_parser - another_parser)
37//
38//      If the parser to refactor is not a unary parser, no refactoring is done
39//      at all.
40//
41//      The original parser should be a binary_parser_category parser,
42//      else the compilation will fail
43//
44///////////////////////////////////////////////////////////////////////////////
45
46template <typename NestedT = non_nested_refactoring>
47class refactor_unary_gen;
48
49template <typename BinaryT, typename NestedT = non_nested_refactoring>
50class refactor_unary_parser :
51    public parser<refactor_unary_parser<BinaryT, NestedT> > {
52
53public:
54    //  the parser to refactor has to be at least a binary_parser_category
55    //  parser
56    BOOST_STATIC_ASSERT((
57        boost::is_convertible<typename BinaryT::parser_category_t,
58            binary_parser_category>::value
59    ));
60
61    refactor_unary_parser(BinaryT const& binary_, NestedT const& nested_)
62    : binary(binary_), nested(nested_) {}
63
64    typedef refactor_unary_parser<BinaryT, NestedT> self_t;
65    typedef refactor_unary_gen<NestedT> parser_generator_t;
66    typedef typename BinaryT::left_t::parser_category_t parser_category_t;
67
68    template <typename ScannerT>
69    typename parser_result<self_t, ScannerT>::type
70    parse(ScannerT const& scan) const
71    {
72        return impl::refactor_unary_type<NestedT>::
73            parse(*this, scan, binary, nested);
74    }
75
76private:
77    typename as_parser<BinaryT>::type::embed_t binary;
78    typename NestedT::embed_t nested;
79};
80
81//////////////////////////////////
82template <typename NestedT>
83class refactor_unary_gen {
84
85public:
86    typedef refactor_unary_gen<NestedT> embed_t;
87
88    refactor_unary_gen(NestedT const& nested_ = non_nested_refactoring())
89    : nested(nested_) {}
90
91    template <typename ParserT>
92    refactor_unary_parser<ParserT, NestedT>
93    operator[](parser<ParserT> const& subject) const
94    {
95        return refactor_unary_parser<ParserT, NestedT>
96            (subject.derived(), nested);
97    }
98
99private:
100    typename NestedT::embed_t nested;
101};
102
103const refactor_unary_gen<> refactor_unary_d = refactor_unary_gen<>();
104
105///////////////////////////////////////////////////////////////////////////////
106//
107//  refactor_action_parser class
108//
109//      This helper template allows to attach an action taken from the left
110//      operand of the given binary parser to a newly constructed parser,
111//      which combines the subject of the left operand of the original binary
112//      parser with the right operand of the original binary parser by means of
113//      the original binary operator parser.
114//
115//      For instance the parser:
116//          some_parser[some_attached_functor] - another_parser
117//
118//      will be refactored to:
119//          (some_parser - another_parser)[some_attached_functor]
120//
121//      If the left operand to refactor is not an action parser, no refactoring
122//      is done at all.
123//
124//      The original parser should be a binary_parser_category parser,
125//      else the compilation will fail
126//
127///////////////////////////////////////////////////////////////////////////////
128
129template <typename NestedT = non_nested_refactoring>
130class refactor_action_gen;
131
132template <typename BinaryT, typename NestedT = non_nested_refactoring>
133class refactor_action_parser :
134    public parser<refactor_action_parser<BinaryT, NestedT> > {
135
136public:
137    //  the parser to refactor has to be at least a binary_parser_category
138    //  parser
139    BOOST_STATIC_ASSERT((
140        boost::is_convertible<typename BinaryT::parser_category_t,
141            binary_parser_category>::value
142    ));
143
144    refactor_action_parser(BinaryT const& binary_, NestedT const& nested_)
145    : binary(binary_), nested(nested_) {}
146
147    typedef refactor_action_parser<BinaryT, NestedT> self_t;
148    typedef refactor_action_gen<NestedT> parser_generator_t;
149    typedef typename BinaryT::left_t::parser_category_t parser_category_t;
150
151    template <typename ScannerT>
152    typename parser_result<self_t, ScannerT>::type
153    parse(ScannerT const& scan) const
154    {
155        return impl::refactor_action_type<NestedT>::
156            parse(*this, scan, binary, nested);
157    }
158
159private:
160    typename as_parser<BinaryT>::type::embed_t binary;
161    typename NestedT::embed_t nested;
162};
163
164//////////////////////////////////
165template <typename NestedT>
166class refactor_action_gen {
167
168public:
169    typedef refactor_action_gen<NestedT> embed_t;
170
171    refactor_action_gen(NestedT const& nested_ = non_nested_refactoring())
172    : nested(nested_) {}
173
174    template <typename ParserT>
175    refactor_action_parser<ParserT, NestedT>
176    operator[](parser<ParserT> const& subject) const
177    {
178        return refactor_action_parser<ParserT, NestedT>
179            (subject.derived(), nested);
180    }
181
182private:
183    typename NestedT::embed_t nested;
184};
185
186const refactor_action_gen<> refactor_action_d = refactor_action_gen<>();
187
188///////////////////////////////////////////////////////////////////////////////
189//
190//  attach_action_parser class
191//
192//      This helper template allows to attach an action given separately
193//      to to all parsers, out of which the given parser is constructed and
194//      reconstructs a new parser having the same structure.
195//
196//      For instance the parser:
197//          (some_parser >> another_parser)[some_attached_functor]
198//
199//      will be refactored to:
200//          some_parser[some_attached_functor]
201//              >> another_parser[some_attached_functor]
202//
203//      The original parser should be a action_parser_category parser,
204//      else the compilation will fail
205//
206//      If the parser, to which the action is attached is not an binary parser,
207//      no refactoring is done at all.
208//
209///////////////////////////////////////////////////////////////////////////////
210
211template <typename NestedT = non_nested_refactoring>
212class attach_action_gen;
213
214template <typename ActionT, typename NestedT = non_nested_refactoring>
215class attach_action_parser :
216    public parser<attach_action_parser<ActionT, NestedT> > {
217
218public:
219    //  the parser to refactor has to be at least a action_parser_category
220    //  parser
221    BOOST_STATIC_ASSERT((
222        boost::is_convertible<typename ActionT::parser_category_t,
223            action_parser_category>::value
224    ));
225
226    attach_action_parser(ActionT const& actor_, NestedT const& nested_)
227    : actor(actor_), nested(nested_) {}
228
229    typedef attach_action_parser<ActionT, NestedT> self_t;
230    typedef attach_action_gen<NestedT> parser_generator_t;
231    typedef typename ActionT::parser_category_t parser_category_t;
232
233    template <typename ScannerT>
234    typename parser_result<self_t, ScannerT>::type
235    parse(ScannerT const& scan) const
236    {
237        return impl::attach_action_type<NestedT>::
238            parse(*this, scan, actor, nested);
239    }
240
241private:
242    typename as_parser<ActionT>::type::embed_t actor;
243    typename NestedT::embed_t nested;
244};
245
246//////////////////////////////////
247template <typename NestedT>
248class attach_action_gen {
249
250public:
251    typedef attach_action_gen<NestedT> embed_t;
252
253    attach_action_gen(NestedT const& nested_ = non_nested_refactoring())
254    : nested(nested_) {}
255
256    template <typename ParserT, typename ActionT>
257    attach_action_parser<action<ParserT, ActionT>, NestedT>
258    operator[](action<ParserT, ActionT> const& actor) const
259    {
260        return attach_action_parser<action<ParserT, ActionT>, NestedT>
261            (actor, nested);
262    }
263
264private:
265    typename NestedT::embed_t nested;
266};
267
268const attach_action_gen<> attach_action_d = attach_action_gen<>();
269
270///////////////////////////////////////////////////////////////////////////////
271}} // namespace boost::spirit
272
273#endif // BOOST_SPIRIT_REFACTORING_HPP
274
Note: See TracBrowser for help on using the repository browser.