1
/*=============================================================================
3
Copyright (c) 1998-2003 Joel de Guzman
4
http://spirit.sourceforge.net/
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
14
///////////////////////////////////////////////////////////////////////////////
17
#include "boost/spirit/core/parser.hpp"
18
#include "boost/spirit/core/composite/composite.hpp"
20
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
21
#include <boost/bind.hpp>
24
///////////////////////////////////////////////////////////////////////////////
25
namespace boost { namespace spirit {
27
///////////////////////////////////////////////////////////////////////////
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:
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
43
// scan.do_action(actor, attribute, first, last);
45
// passing in these information:
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
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:
61
// void func(Iterator first, Iterator last); // functions
63
// struct ftor // functors
65
// void func(Iterator first, Iterator last) const;
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
72
// If the attribute type of the parser being wrapped is not a nil_t,
73
// the function or functor usually expect the signature:
75
// void func(T val); // functions
77
// struct ftor // functors
79
// void func(T val) const;
82
// where T is the attribute type and val is the attribute value
83
// returned by the parser being wrapped.
85
///////////////////////////////////////////////////////////////////////////
86
template <typename ParserT, typename ActionT>
87
class action : public unary<ParserT, parser<action<ParserT, ActionT> > >
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;
96
template <typename ScannerT>
99
typedef typename parser_result<ParserT, ScannerT>::type type;
104
, actor(ActionT()) {}
106
action(ParserT const& p, ActionT const& a)
110
template <typename ScannerT>
111
typename parser_result<self_t, ScannerT>::type
112
parse(ScannerT const& scan) const
114
typedef typename ScannerT::iterator_t iterator_t;
115
typedef typename parser_result<self_t, ScannerT>::type result_t;
117
scan.at_end(); // allow skipper to take effect
118
iterator_t save = scan.first;
119
result_t hit = this->subject().parse(scan);
121
scan.do_action(actor, hit.value(), save, scan.first);
125
ActionT const& predicate() const { return actor; }
132
///////////////////////////////////////////////////////////////////////////
134
// assign_actor class
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).
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.
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:
152
// where v is the variable and value is the extracted result
155
// 2 The other function call operator that takes in the
156
// first/last iterator expects the variable to accept the
159
// v.assign(first, last);
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.
165
// Requirements 1 and 2 are exclusive and applies only if the
166
// corresponding single or double argument operator is actually
169
// Instances of assign_actor are not created directly. Instead a
170
// generator function:
174
// taking in a reference to a variable of arbitrary type is used to
175
// instantiate an assign_actor object of the proper type.
177
///////////////////////////////////////////////////////////////////////////
178
template <typename T>
184
assign_actor(T& ref_)
187
template <typename T2>
188
void operator()(T2 const& val) const
191
template <typename IteratorT>
192
void operator()(IteratorT const& first, IteratorT const& last) const
193
{ ref.assign(first, last); }
200
//////////////////////////////////
201
// MSVC6 Workaround for assigning to strings from custom iterators
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)
212
class assign_actor<std::string>
216
assign_actor(std::string& ref_)
219
template <typename T2>
220
void operator()(T2 const& val) const
223
template <typename IteratorT>
224
void operator()(IteratorT const& f, IteratorT const& l) const
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.
232
boost::bind(&assign_actor<std::string>::string_push_back,
238
void string_push_back(char ch)
246
//////////////////////////////////
247
template <typename T>
248
inline assign_actor<T> const
251
return assign_actor<T>(ref);
254
///////////////////////////////////////////////////////////////////////////
256
// append_actor class
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).
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.
268
// 1 The variable is assumed to be a container of some sort. An
269
// STL container is a perfectly valid candidate.
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:
275
// c.insert(c.end(), value)
277
// where c is the container and value is the extracted result
280
// 2.a The container is required to have a member function
281
// end() that returns an iterator to its 'end' element.
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.
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:
292
// c.insert(c.end(), T::value_type(first, last));
294
// where c is the container and T is the container type. In
295
// addition to the requirements 1 and 2 above,
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.
301
// Requirement 2 is exclusive of requirement 3. Requirement 3
302
// only applies if the corresponding double argument operator
303
// is actually called.
305
// Instances of append_actor are not created directly. Instead a
306
// generator function:
310
// taking in a reference to a variable of arbitrary type is used to
311
// instantiate an append_actor object of the proper type.
313
///////////////////////////////////////////////////////////////////////////
314
template <typename T>
320
append_actor(T& ref_)
323
template <typename T2>
324
void operator()(T2 const& val) const
325
{ ref.insert(ref.end(), val); }
327
template <typename IteratorT>
328
void operator()(IteratorT const& first, IteratorT const& last) const
330
typedef typename T::value_type value_type;
331
ref.insert(ref.end(), value_type(first, last));
339
//////////////////////////////////
340
template <typename T>
341
inline append_actor<T> const
344
return append_actor<T>(ref);
347
}} // namespace boost::spirit