]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
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 | |
77 | 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 | ||
95 | refactor_unary_gen(NestedT const& nested_ = non_nested_refactoring()) | |
96 | : nested(nested_) {} | |
97 | ||
98 | template <typename ParserT> | |
99 | refactor_unary_parser<ParserT, NestedT> | |
100 | 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 | ||
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 | |
160 | 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 | ||
178 | refactor_action_gen(NestedT const& nested_ = non_nested_refactoring()) | |
179 | : nested(nested_) {} | |
180 | ||
181 | template <typename ParserT> | |
182 | refactor_action_parser<ParserT, NestedT> | |
183 | 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 | ||
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 | |
242 | 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 | ||
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> | |
265 | 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 |