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