summaryrefslogtreecommitdiff
path: root/boost/spirit/home/classic/meta/refactoring.hpp
blob: e5d45f92974225fe1e449fd3b989a0c954163a1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*=============================================================================
    Copyright (c) 2002-2003 Hartmut Kaiser
    http://spirit.sourceforge.net/

  Distributed under the Boost Software License, Version 1.0. (See accompanying
  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef BOOST_SPIRIT_REFACTORING_HPP
#define BOOST_SPIRIT_REFACTORING_HPP

///////////////////////////////////////////////////////////////////////////////
#include <boost/static_assert.hpp>
#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/meta/as_parser.hpp>
#include <boost/spirit/home/classic/core/parser.hpp>
#include <boost/spirit/home/classic/core/composite/composite.hpp>
#include <boost/spirit/home/classic/meta/impl/refactoring.ipp>

///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {

BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN

#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif

///////////////////////////////////////////////////////////////////////////////
//
//  refactor_unary_parser class
//
//      This helper template allows to attach an unary operation to a newly
//      constructed parser, which combines the subject of the left operand of
//      the original given parser (BinaryT) with the right operand of the
//      original binary parser through the original binary operation and
//      rewraps the resulting parser with the original unary operator.
//
//      For instance given the parser:
//          *some_parser - another_parser
//
//      will be refactored to:
//          *(some_parser - another_parser)
//
//      If the parser to refactor is not a unary parser, no refactoring is done
//      at all.
//
//      The original parser should be a binary_parser_category parser,
//      else the compilation will fail
//
///////////////////////////////////////////////////////////////////////////////

template <typename NestedT = non_nested_refactoring>
class refactor_unary_gen;

template <typename BinaryT, typename NestedT = non_nested_refactoring>
class refactor_unary_parser :
    public parser<refactor_unary_parser<BinaryT, NestedT> > {

public:
    //  the parser to refactor has to be at least a binary_parser_category
    //  parser
    BOOST_STATIC_ASSERT((
        boost::is_convertible<typename BinaryT::parser_category_t,
            binary_parser_category>::value
    ));

    refactor_unary_parser(BinaryT const& binary_, NestedT const& nested_)
    : binary(binary_), nested(nested_) {}

    typedef refactor_unary_parser<BinaryT, NestedT> self_t;
    typedef refactor_unary_gen<NestedT> parser_generator_t;
    typedef typename BinaryT::left_t::parser_category_t parser_category_t;

    template <typename ScannerT>
    typename parser_result<self_t, ScannerT>::type
    parse(ScannerT const& scan) const
    {
        return impl::refactor_unary_type<NestedT>::
            parse(*this, scan, binary, nested);
    }

private:
    typename as_parser<BinaryT>::type::embed_t binary;
    typename NestedT::embed_t nested;
};

//////////////////////////////////
template <typename NestedT>
class refactor_unary_gen {

public:
    typedef refactor_unary_gen<NestedT> embed_t;

    refactor_unary_gen(NestedT const& nested_ = non_nested_refactoring())
    : nested(nested_) {}

    template <typename ParserT>
    refactor_unary_parser<ParserT, NestedT>
    operator[](parser<ParserT> const& subject) const
    {
        return refactor_unary_parser<ParserT, NestedT>
            (subject.derived(), nested);
    }

private:
    typename NestedT::embed_t nested;
};

const refactor_unary_gen<> refactor_unary_d = refactor_unary_gen<>();

///////////////////////////////////////////////////////////////////////////////
//
//  refactor_action_parser class
//
//      This helper template allows to attach an action taken from the left
//      operand of the given binary parser to a newly constructed parser,
//      which combines the subject of the left operand of the original binary
//      parser with the right operand of the original binary parser by means of
//      the original binary operator parser.
//
//      For instance the parser:
//          some_parser[some_attached_functor] - another_parser
//
//      will be refactored to:
//          (some_parser - another_parser)[some_attached_functor]
//
//      If the left operand to refactor is not an action parser, no refactoring
//      is done at all.
//
//      The original parser should be a binary_parser_category parser,
//      else the compilation will fail
//
///////////////////////////////////////////////////////////////////////////////

template <typename NestedT = non_nested_refactoring>
class refactor_action_gen;

template <typename BinaryT, typename NestedT = non_nested_refactoring>
class refactor_action_parser :
    public parser<refactor_action_parser<BinaryT, NestedT> > {

public:
    //  the parser to refactor has to be at least a binary_parser_category
    //  parser
    BOOST_STATIC_ASSERT((
        boost::is_convertible<typename BinaryT::parser_category_t,
            binary_parser_category>::value
    ));

    refactor_action_parser(BinaryT const& binary_, NestedT const& nested_)
    : binary(binary_), nested(nested_) {}

    typedef refactor_action_parser<BinaryT, NestedT> self_t;
    typedef refactor_action_gen<NestedT> parser_generator_t;
    typedef typename BinaryT::left_t::parser_category_t parser_category_t;

    template <typename ScannerT>
    typename parser_result<self_t, ScannerT>::type
    parse(ScannerT const& scan) const
    {
        return impl::refactor_action_type<NestedT>::
            parse(*this, scan, binary, nested);
    }

private:
    typename as_parser<BinaryT>::type::embed_t binary;
    typename NestedT::embed_t nested;
};

//////////////////////////////////
template <typename NestedT>
class refactor_action_gen {

public:
    typedef refactor_action_gen<NestedT> embed_t;

    refactor_action_gen(NestedT const& nested_ = non_nested_refactoring())
    : nested(nested_) {}

    template <typename ParserT>
    refactor_action_parser<ParserT, NestedT>
    operator[](parser<ParserT> const& subject) const
    {
        return refactor_action_parser<ParserT, NestedT>
            (subject.derived(), nested);
    }

private:
    typename NestedT::embed_t nested;
};

const refactor_action_gen<> refactor_action_d = refactor_action_gen<>();

///////////////////////////////////////////////////////////////////////////////
//
//  attach_action_parser class
//
//      This helper template allows to attach an action given separately
//      to to all parsers, out of which the given parser is constructed and
//      reconstructs a new parser having the same structure.
//
//      For instance the parser:
//          (some_parser >> another_parser)[some_attached_functor]
//
//      will be refactored to:
//          some_parser[some_attached_functor]
//              >> another_parser[some_attached_functor]
//
//      The original parser should be a action_parser_category parser,
//      else the compilation will fail
//
//      If the parser, to which the action is attached is not an binary parser,
//      no refactoring is done at all.
//
///////////////////////////////////////////////////////////////////////////////

template <typename NestedT = non_nested_refactoring>
class attach_action_gen;

template <typename ActionT, typename NestedT = non_nested_refactoring>
class attach_action_parser :
    public parser<attach_action_parser<ActionT, NestedT> > {

public:
    //  the parser to refactor has to be at least a action_parser_category
    //  parser
    BOOST_STATIC_ASSERT((
        boost::is_convertible<typename ActionT::parser_category_t,
            action_parser_category>::value
    ));

    attach_action_parser(ActionT const& actor_, NestedT const& nested_)
    : actor(actor_), nested(nested_) {}

    typedef attach_action_parser<ActionT, NestedT> self_t;
    typedef attach_action_gen<NestedT> parser_generator_t;
    typedef typename ActionT::parser_category_t parser_category_t;

    template <typename ScannerT>
    typename parser_result<self_t, ScannerT>::type
    parse(ScannerT const& scan) const
    {
        return impl::attach_action_type<NestedT>::
            parse(*this, scan, actor, nested);
    }

private:
    typename as_parser<ActionT>::type::embed_t actor;
    typename NestedT::embed_t nested;
};

//////////////////////////////////
template <typename NestedT>
class attach_action_gen {

public:
    typedef attach_action_gen<NestedT> embed_t;

    attach_action_gen(NestedT const& nested_ = non_nested_refactoring())
    : nested(nested_) {}

    template <typename ParserT, typename ActionT>
    attach_action_parser<action<ParserT, ActionT>, NestedT>
    operator[](action<ParserT, ActionT> const& actor) const
    {
        return attach_action_parser<action<ParserT, ActionT>, NestedT>
            (actor, nested);
    }

private:
    typename NestedT::embed_t nested;
};

const attach_action_gen<> attach_action_d = attach_action_gen<>();

#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif

///////////////////////////////////////////////////////////////////////////////
BOOST_SPIRIT_CLASSIC_NAMESPACE_END

}} // namespace BOOST_SPIRIT_CLASSIC_NS

#endif // BOOST_SPIRIT_REFACTORING_HPP