~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to boost/boost/spirit/core/composite/actions.hpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*=============================================================================
 
2
    Spirit v1.6.1
 
3
    Copyright (c) 1998-2003 Joel de Guzman
 
4
    http://spirit.sourceforge.net/
 
5
 
 
6
    Permission to copy, use, modify, sell and distribute this software is
 
7
    granted provided this copyright notice appears in all copies. This
 
8
    software is provided "as is" without express or implied warranty, and
 
9
    with no claim as to its suitability for any purpose.
 
10
=============================================================================*/
 
11
#ifndef BOOST_SPIRIT_ACTIONS_HPP
 
12
#define BOOST_SPIRIT_ACTIONS_HPP
 
13
 
 
14
///////////////////////////////////////////////////////////////////////////////
 
15
#include <algorithm>
 
16
 
 
17
#include "boost/spirit/core/parser.hpp"
 
18
#include "boost/spirit/core/composite/composite.hpp"
 
19
 
 
20
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
 
21
#include <boost/bind.hpp>
 
22
#endif
 
23
 
 
24
///////////////////////////////////////////////////////////////////////////////
 
25
namespace boost { namespace spirit {
 
26
 
 
27
    ///////////////////////////////////////////////////////////////////////////
 
28
    //
 
29
    //  action class
 
30
    //
 
31
    //      The action class binds a parser with a user defined semantic
 
32
    //      action. Instances of action are never created manually. Instead,
 
33
    //      action objects are typically created indirectly through
 
34
    //      expression templates of the form:
 
35
    //
 
36
    //          p[f]
 
37
    //
 
38
    //      where p is a parser and f is a function or functor. The semantic
 
39
    //      action may be a function or a functor. When the parser is
 
40
    //      successful, the actor calls the scanner's action_policy policy
 
41
    //      (see scanner.hpp):
 
42
    //
 
43
    //          scan.do_action(actor, attribute, first, last);
 
44
    //
 
45
    //      passing in these information:
 
46
    //
 
47
    //          actor:        The action's function or functor
 
48
    //          attribute:    The match (returned by the parser) object's
 
49
    //                        attribute (see match.hpp)
 
50
    //          first:        Iterator pointing to the start of the matching
 
51
    //                        portion of the input
 
52
    //          last:         Iterator pointing to one past the end of the
 
53
    //                        matching portion of the input
 
54
    //
 
55
    //      It is the responsibility of the scanner's action_policy policy to
 
56
    //      dispatch the function or functor as it sees fit. The expected
 
57
    //      function or functor signature depends on the parser being
 
58
    //      wrapped. In general, if the attribute type of the parser being
 
59
    //      wrapped is a nil_t, the function or functor expect the signature:
 
60
    //
 
61
    //          void func(Iterator first, Iterator last); // functions
 
62
    //
 
63
    //          struct ftor // functors
 
64
    //          {
 
65
    //              void func(Iterator first, Iterator last) const;
 
66
    //          };
 
67
    //
 
68
    //      where Iterator is the type of the iterator that is being used and
 
69
    //      first and last are the iterators pointing to the matching portion
 
70
    //      of the input.
 
71
    //
 
72
    //      If the attribute type of the parser being wrapped is not a nil_t,
 
73
    //      the function or functor usually expect the signature:
 
74
    //
 
75
    //          void func(T val); // functions
 
76
    //
 
77
    //          struct ftor // functors
 
78
    //          {
 
79
    //              void func(T val) const;
 
80
    //          };
 
81
    //
 
82
    //      where T is the attribute type and val is the attribute value
 
83
    //      returned by the parser being wrapped.
 
84
    //
 
85
    ///////////////////////////////////////////////////////////////////////////
 
86
    template <typename ParserT, typename ActionT>
 
87
    class action : public unary<ParserT, parser<action<ParserT, ActionT> > >
 
88
    {
 
89
    public:
 
90
 
 
91
        typedef action<ParserT, ActionT>        self_t;
 
92
        typedef action_parser_category          parser_category_t;
 
93
        typedef unary<ParserT, parser<self_t> > base_t;
 
94
        typedef ActionT                         predicate_t;
 
95
 
 
96
        template <typename ScannerT>
 
97
        struct result
 
98
        {
 
99
            typedef typename parser_result<ParserT, ScannerT>::type type;
 
100
        };
 
101
 
 
102
        action()
 
103
        : base_t(ParserT())
 
104
        , actor(ActionT()) {}
 
105
 
 
106
        action(ParserT const& p, ActionT const& a)
 
107
        : base_t(p)
 
108
        , actor(a) {}
 
109
 
 
110
        template <typename ScannerT>
 
111
        typename parser_result<self_t, ScannerT>::type
 
112
        parse(ScannerT const& scan) const
 
113
        {
 
114
            typedef typename ScannerT::iterator_t iterator_t;
 
115
            typedef typename parser_result<self_t, ScannerT>::type result_t;
 
116
 
 
117
            scan.at_end(); // allow skipper to take effect
 
118
            iterator_t save = scan.first;
 
119
            result_t hit = this->subject().parse(scan);
 
120
            if (hit)
 
121
                scan.do_action(actor, hit.value(), save, scan.first);
 
122
            return hit;
 
123
        }
 
124
 
 
125
        ActionT const& predicate() const { return actor; }
 
126
 
 
127
    private:
 
128
 
 
129
        ActionT actor;
 
130
    };
 
131
 
 
132
    ///////////////////////////////////////////////////////////////////////////
 
133
    //
 
134
    //  assign_actor class
 
135
    //
 
136
    //      assign_actor is a predefined semantic action functor. It can be
 
137
    //      used to extract the result of a successful parse and assign it to
 
138
    //      a variable. The functor overloads two function call operators:
 
139
    //      operator(), one that takes in a single value argument and another
 
140
    //      that accepts two iterators (first and last).
 
141
    //
 
142
    //      The constructor expects a reference to a variable. The functor is
 
143
    //      polymorphic and should work with any variable type as long as it
 
144
    //      is compatible with the requirements outlined below.
 
145
    //
 
146
    //          1 The single argument function call operator assigns the
 
147
    //            argument received to the variable. The variable is required
 
148
    //            to accept the statement:
 
149
    //
 
150
    //                v = value;
 
151
    //
 
152
    //            where v is the variable and value is the extracted result
 
153
    //            of the parser.
 
154
    //
 
155
    //          2 The other function call operator that takes in the
 
156
    //            first/last iterator expects the variable to accept the
 
157
    //            statement:
 
158
    //
 
159
    //                v.assign(first, last);
 
160
    //
 
161
    //            2.a The variable has a member function assign, taking in
 
162
    //                the iterator pair. Any STL container that has an
 
163
    //                assign(first, last) member function may be used.
 
164
    //
 
165
    //          Requirements 1 and 2 are exclusive and applies only if the
 
166
    //          corresponding single or double argument operator is actually
 
167
    //          called.
 
168
    //
 
169
    //      Instances of assign_actor are not created directly. Instead a
 
170
    //      generator function:
 
171
    //
 
172
    //          assign(T& ref)
 
173
    //
 
174
    //      taking in a reference to a variable of arbitrary type is used to
 
175
    //      instantiate an assign_actor object of the proper type.
 
176
    //
 
177
    ///////////////////////////////////////////////////////////////////////////
 
178
    template <typename T>
 
179
    class assign_actor
 
180
    {
 
181
    public:
 
182
 
 
183
        explicit
 
184
        assign_actor(T& ref_)
 
185
        : ref(ref_) {}
 
186
 
 
187
        template <typename T2>
 
188
        void operator()(T2 const& val) const
 
189
        { ref = val; }
 
190
 
 
191
        template <typename IteratorT>
 
192
        void operator()(IteratorT const& first, IteratorT const& last) const
 
193
        { ref.assign(first, last); }
 
194
 
 
195
    private:
 
196
 
 
197
        T& ref;
 
198
    };
 
199
 
 
200
    //////////////////////////////////
 
201
    // MSVC6 Workaround for assigning to strings from custom iterators
 
202
    //
 
203
    // MSVC6 does not support custom iterators in string::assign()
 
204
    // because it does not support partial ordering of member templates. 
 
205
    // In other places of the standard library, this was fixed by supporting 
 
206
    // any iterator inherited from std::iterator (and all Spirit's iterators, 
 
207
    // as iterator_adaptor's generated ones, do that), but this is not the 
 
208
    // case here. So, we create a specialization to handle it manually.
 
209
    //////////////////////////////////
 
210
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
 
211
    template <>
 
212
    class assign_actor<std::string>
 
213
    {
 
214
    public:
 
215
        explicit
 
216
            assign_actor(std::string& ref_)
 
217
            : ref(ref_) {}
 
218
 
 
219
            template <typename T2>
 
220
            void operator()(T2 const& val) const
 
221
            { ref = val; }
 
222
 
 
223
            template <typename IteratorT>
 
224
            void operator()(IteratorT const& f, IteratorT const& l) const
 
225
            { 
 
226
                // Here I tried several alternatives, but all the obvious ones
 
227
                //  are not supported by MSVC6. For instance, std::string does
 
228
                //  not have a push_back() member function, so we can't use
 
229
                //  std::copy with back_inserter. This is the best solution I
 
230
                //  could come up with.
 
231
                std::for_each(f, l, 
 
232
                    boost::bind(&assign_actor<std::string>::string_push_back, 
 
233
                        this, _1)
 
234
                );
 
235
            }
 
236
 
 
237
    private:
 
238
        void string_push_back(char ch)
 
239
        { ref += ch; }
 
240
 
 
241
        std::string& ref;
 
242
    };
 
243
#endif
 
244
    
 
245
    
 
246
    //////////////////////////////////
 
247
    template <typename T>
 
248
    inline assign_actor<T> const
 
249
    assign(T& ref)
 
250
    {
 
251
        return assign_actor<T>(ref);
 
252
    }
 
253
 
 
254
    ///////////////////////////////////////////////////////////////////////////
 
255
    //
 
256
    //  append_actor class
 
257
    //
 
258
    //      append_actor is a predefined semantic action functor. It can be
 
259
    //      used to extract the result of a successful parse and append it to
 
260
    //      a variable. The functor overloads two function call operators:
 
261
    //      operator(), one that takes in a single value argument and another
 
262
    //      that accepts two iterators (first and last).
 
263
    //
 
264
    //      The constructor expects a reference to a variable. The functor is
 
265
    //      polymorphic and should work with any variable type as long as it
 
266
    //      is compatible with the requirements outlined below.
 
267
    //
 
268
    //          1 The variable is assumed to be a container of some sort. An
 
269
    //            STL container is a perfectly valid candidate.
 
270
    //
 
271
    //          2 The single argument function call operator appends the
 
272
    //            extracted parser result and appends it to the container.
 
273
    //            The container is required to accept the statement:
 
274
    //
 
275
    //                c.insert(c.end(), value)
 
276
    //
 
277
    //            where c is the container and value is the extracted result
 
278
    //            of the parser.
 
279
    //
 
280
    //            2.a The container is required to have a member function
 
281
    //                end() that returns an iterator to its 'end' element.
 
282
    //
 
283
    //            2.b The container is required to have a member function
 
284
    //                insert that takes in the 'end' iterator and a value
 
285
    //                compatible with the container's element type.
 
286
    //
 
287
    //          3 The function call operator that takes in the first/last
 
288
    //            iterator first constructs a value from the iterator pair
 
289
    //            before appending the value to the container. The container
 
290
    //            is required to accept the statement:
 
291
    //
 
292
    //                c.insert(c.end(), T::value_type(first, last));
 
293
    //
 
294
    //            where c is the container and T is the container type. In
 
295
    //            addition to the requirements 1 and 2 above,
 
296
    //
 
297
    //            3.a The container is also required to have a typedef
 
298
    //                value_type (the container's value type) that can be
 
299
    //                constructed given a first/last iterator pair.
 
300
    //
 
301
    //          Requirement 2 is exclusive of requirement 3. Requirement 3
 
302
    //          only applies if the corresponding double argument operator
 
303
    //          is actually called.
 
304
    //
 
305
    //      Instances of append_actor are not created directly. Instead a
 
306
    //      generator function:
 
307
    //
 
308
    //          append(T& ref)
 
309
    //
 
310
    //      taking in a reference to a variable of arbitrary type is used to
 
311
    //      instantiate an append_actor object of the proper type.
 
312
    //
 
313
    ///////////////////////////////////////////////////////////////////////////
 
314
    template <typename T>
 
315
    class append_actor
 
316
    {
 
317
    public:
 
318
 
 
319
        explicit
 
320
        append_actor(T& ref_)
 
321
        : ref(ref_) {}
 
322
 
 
323
        template <typename T2>
 
324
        void operator()(T2 const& val) const
 
325
        { ref.insert(ref.end(), val); }
 
326
 
 
327
        template <typename IteratorT>
 
328
        void operator()(IteratorT const& first, IteratorT const& last) const
 
329
        {
 
330
            typedef typename T::value_type value_type;
 
331
            ref.insert(ref.end(), value_type(first, last));
 
332
        }
 
333
 
 
334
    private:
 
335
 
 
336
        T& ref;
 
337
    };
 
338
 
 
339
    //////////////////////////////////
 
340
    template <typename T>
 
341
    inline append_actor<T> const
 
342
    append(T& ref)
 
343
    {
 
344
        return append_actor<T>(ref);
 
345
    }
 
346
 
 
347
}} // namespace boost::spirit
 
348
 
 
349
#endif