]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/include/boost/spirit/home/classic/utility/lists.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / classic / utility / lists.hpp
CommitLineData
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_LISTS_HPP
9#define BOOST_SPIRIT_LISTS_HPP
10
11///////////////////////////////////////////////////////////////////////////////
12#include <boost/config.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
18#include <boost/spirit/home/classic/utility/lists_fwd.hpp>
19#include <boost/spirit/home/classic/utility/impl/lists.ipp>
20
21///////////////////////////////////////////////////////////////////////////////
22namespace boost { namespace spirit {
23
24BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
25
26///////////////////////////////////////////////////////////////////////////////
27//
28// list_parser class
29//
30// List parsers allow to parse constructs like
31//
32// item >> *(delim >> item)
33//
34// where 'item' is an auxiliary expression to parse and 'delim' is an
35// auxiliary delimiter to parse.
36//
37// The list_parser class also can match an optional closing delimiter
38// represented by the 'end' parser at the end of the list:
39//
40// item >> *(delim >> item) >> !end.
41//
42// If ItemT is an action_parser_category type (parser with an attached
43// semantic action) we have to do something special. This happens, if the
44// user wrote something like:
45//
46// list_p(item[f], delim)
47//
48// where 'item' is the parser matching one item of the list sequence and
49// 'f' is a functor to be called after matching one item. If we would do
50// nothing, the resulting code would parse the sequence as follows:
51//
52// (item[f] - delim) >> *(delim >> (item[f] - delim))
53//
54// what in most cases is not what the user expects.
55// (If this _is_ what you've expected, then please use one of the list_p
56// generator functions 'direct()', which will inhibit re-attaching
57// the actor to the item parser).
58//
59// To make the list parser behave as expected:
60//
61// (item - delim)[f] >> *(delim >> (item - delim)[f])
62//
63// the actor attached to the 'item' parser has to be re-attached to the
64// *(item - delim) parser construct, which will make the resulting list
65// parser 'do the right thing'.
66//
67// Additionally special care must be taken, if the item parser is a
68// unary_parser_category type parser as
69//
70// list_p(*anychar_p, ',')
71//
72// which without any refactoring would result in
73//
74// (*anychar_p - ch_p(','))
75// >> *( ch_p(',') >> (*anychar_p - ch_p(',')) )
76//
77// and will not give the expected result (the first *anychar_p will eat up
78// all the input up to the end of the input stream). So we have to
79// refactor this into:
80//
81// *(anychar_p - ch_p(','))
82// >> *( ch_p(',') >> *(anychar_p - ch_p(',')) )
83//
84// what will give the correct result.
85//
86// The case, where the item parser is a combination of the two mentioned
87// problems (i.e. the item parser is a unary parser with an attached
88// action), is handled accordingly too:
89//
90// list_p((*anychar_p)[f], ',')
91//
92// will be parsed as expected:
93//
94// (*(anychar_p - ch_p(',')))[f]
95// >> *( ch_p(',') >> (*(anychar_p - ch_p(',')))[f] ).
96//
97///////////////////////////////////////////////////////////////////////////////
98template <
99 typename ItemT, typename DelimT, typename EndT, typename CategoryT
100>
101struct list_parser :
102 public parser<list_parser<ItemT, DelimT, EndT, CategoryT> > {
103
104 typedef list_parser<ItemT, DelimT, EndT, CategoryT> self_t;
105 typedef CategoryT parser_category_t;
106
107 list_parser(ItemT const &item_, DelimT const &delim_,
108 EndT const& end_ = no_list_endtoken())
109 : item(item_), delim(delim_), end(end_)
110 {}
111
112 template <typename ScannerT>
113 typename parser_result<self_t, ScannerT>::type
114 parse(ScannerT const& scan) const
115 {
116 return impl::list_parser_type<CategoryT>
117 ::parse(scan, *this, item, delim, end);
118 }
119
120private:
121 typename as_parser<ItemT>::type::embed_t item;
122 typename as_parser<DelimT>::type::embed_t delim;
123 typename as_parser<EndT>::type::embed_t end;
124};
125
126///////////////////////////////////////////////////////////////////////////////
127//
128// List parser generator template
129//
130// This is a helper for generating a correct list_parser<> from
131// auxiliary parameters. There are the following types supported as
132// parameters yet: parsers, single characters and strings (see
133// as_parser<> in meta/as_parser.hpp).
134//
135// The list_parser_gen by itself can be used for parsing comma separated
136// lists without item formatting:
137//
138// list_p.parse(...)
139// matches any comma separated list.
140//
141// If list_p is used with one parameter, this parameter is used to match
142// the delimiter:
143//
144// list_p(';').parse(...)
145// matches any semicolon separated list.
146//
147// If list_p is used with two parameters, the first parameter is used to
148// match the items and the second parameter matches the delimiters:
149//
150// list_p(uint_p, ',').parse(...)
151// matches comma separated unsigned integers.
152//
153// If list_p is used with three parameters, the first parameter is used
154// to match the items, the second one is used to match the delimiters and
155// the third one is used to match an optional ending token sequence:
156//
157// list_p(real_p, ';', eol_p).parse(...)
158// matches a semicolon separated list of real numbers optionally
159// followed by an end of line.
160//
161// The list_p in the previous examples denotes the predefined parser
162// generator, which should be used to define list parsers (see below).
163//
164///////////////////////////////////////////////////////////////////////////////
165
166template <typename CharT = char>
167struct list_parser_gen :
168 public list_parser<kleene_star<anychar_parser>, chlit<CharT> >
169{
170 typedef list_parser_gen<CharT> self_t;
171
172// construct the list_parser_gen object as an list parser for comma separated
173// lists without item formatting.
174 list_parser_gen()
175 : list_parser<kleene_star<anychar_parser>, chlit<CharT> >
176 (*anychar_p, chlit<CharT>(','))
177 {}
178
179// The following generator functions should be used under normal circumstances.
180// (the operator()(...) functions)
181
182 // Generic generator functions for creation of concrete list parsers, which
183 // support 'normal' syntax:
184 //
185 // item >> *(delim >> item)
186 //
187 // If item isn't given, everything between two delimiters is matched.
188
189 template<typename DelimT>
190 list_parser<
191 kleene_star<anychar_parser>,
192 typename as_parser<DelimT>::type,
193 no_list_endtoken,
194 unary_parser_category // there is no action to re-attach
195 >
196 operator()(DelimT const &delim_) const
197 {
198 typedef kleene_star<anychar_parser> item_t;
199 typedef typename as_parser<DelimT>::type delim_t;
200
201 typedef
202 list_parser<item_t, delim_t, no_list_endtoken, unary_parser_category>
203 return_t;
204
205 return return_t(*anychar_p, as_parser<DelimT>::convert(delim_));
206 }
207
208 template<typename ItemT, typename DelimT>
209 list_parser<
210 typename as_parser<ItemT>::type,
211 typename as_parser<DelimT>::type,
212 no_list_endtoken,
213 typename as_parser<ItemT>::type::parser_category_t
214 >
215 operator()(ItemT const &item_, DelimT const &delim_) const
216 {
217 typedef typename as_parser<ItemT>::type item_t;
218 typedef typename as_parser<DelimT>::type delim_t;
219 typedef list_parser<item_t, delim_t, no_list_endtoken,
220 BOOST_DEDUCED_TYPENAME item_t::parser_category_t>
221 return_t;
222
223 return return_t(
224 as_parser<ItemT>::convert(item_),
225 as_parser<DelimT>::convert(delim_)
226 );
227 }
228
229 // Generic generator function for creation of concrete list parsers, which
230 // support 'extended' syntax:
231 //
232 // item >> *(delim >> item) >> !end
233
234 template<typename ItemT, typename DelimT, typename EndT>
235 list_parser<
236 typename as_parser<ItemT>::type,
237 typename as_parser<DelimT>::type,
238 typename as_parser<EndT>::type,
239 typename as_parser<ItemT>::type::parser_category_t
240 >
241 operator()(
242 ItemT const &item_, DelimT const &delim_, EndT const &end_) const
243 {
244 typedef typename as_parser<ItemT>::type item_t;
245 typedef typename as_parser<DelimT>::type delim_t;
246 typedef typename as_parser<EndT>::type end_t;
247
248 typedef list_parser<item_t, delim_t, end_t,
249 BOOST_DEDUCED_TYPENAME item_t::parser_category_t>
250 return_t;
251
252 return return_t(
253 as_parser<ItemT>::convert(item_),
254 as_parser<DelimT>::convert(delim_),
255 as_parser<EndT>::convert(end_)
256 );
257 }
258
259// The following functions should be used, if the 'item' parser has an attached
260// semantic action or is a unary_parser_category type parser and the structure
261// of the resulting list parser should _not_ be refactored during parser
262// construction (see comment above).
263
264 // Generic generator function for creation of concrete list parsers, which
265 // support 'normal' syntax:
266 //
267 // item >> *(delim >> item)
268
269 template<typename ItemT, typename DelimT>
270 list_parser<
271 typename as_parser<ItemT>::type,
272 typename as_parser<DelimT>::type,
273 no_list_endtoken,
274 plain_parser_category // inhibit action re-attachment
275 >
276 direct(ItemT const &item_, DelimT const &delim_) const
277 {
278 typedef typename as_parser<ItemT>::type item_t;
279 typedef typename as_parser<DelimT>::type delim_t;
280 typedef list_parser<item_t, delim_t, no_list_endtoken,
281 plain_parser_category>
282 return_t;
283
284 return return_t(
285 as_parser<ItemT>::convert(item_),
286 as_parser<DelimT>::convert(delim_)
287 );
288 }
289
290 // Generic generator function for creation of concrete list parsers, which
291 // support 'extended' syntax:
292 //
293 // item >> *(delim >> item) >> !end
294
295 template<typename ItemT, typename DelimT, typename EndT>
296 list_parser<
297 typename as_parser<ItemT>::type,
298 typename as_parser<DelimT>::type,
299 typename as_parser<EndT>::type,
300 plain_parser_category // inhibit action re-attachment
301 >
302 direct(
303 ItemT const &item_, DelimT const &delim_, EndT const &end_) const
304 {
305 typedef typename as_parser<ItemT>::type item_t;
306 typedef typename as_parser<DelimT>::type delim_t;
307 typedef typename as_parser<EndT>::type end_t;
308
309 typedef
310 list_parser<item_t, delim_t, end_t, plain_parser_category>
311 return_t;
312
313 return return_t(
314 as_parser<ItemT>::convert(item_),
315 as_parser<DelimT>::convert(delim_),
316 as_parser<EndT>::convert(end_)
317 );
318 }
319};
320
321///////////////////////////////////////////////////////////////////////////////
322//
323// Predefined list parser generator
324//
325// The list_p parser generator can be used
326// - by itself for parsing comma separated lists without item formatting
327// or
328// - for generating list parsers with auxiliary parser parameters
329// for the 'item', 'delim' and 'end' subsequences.
330// (see comment above)
331//
332///////////////////////////////////////////////////////////////////////////////
333const list_parser_gen<> list_p = list_parser_gen<>();
334
335///////////////////////////////////////////////////////////////////////////////
336BOOST_SPIRIT_CLASSIC_NAMESPACE_END
337
338}} // namespace BOOST_SPIRIT_CLASSIC_NS
339
340#endif