Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Copyright (c) 2001-2003 Daniel Nuffer
|
Chris@16
|
3 Copyright (c) 2001-2007 Hartmut Kaiser
|
Chris@16
|
4 Revised 2007, Copyright (c) Tobias Schwinger
|
Chris@16
|
5 http://spirit.sourceforge.net/
|
Chris@16
|
6
|
Chris@16
|
7 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9 =============================================================================*/
|
Chris@16
|
10 #ifndef BOOST_SPIRIT_TREE_COMMON_HPP
|
Chris@16
|
11 #define BOOST_SPIRIT_TREE_COMMON_HPP
|
Chris@16
|
12
|
Chris@16
|
13 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
14 #include <vector>
|
Chris@16
|
15 #else
|
Chris@16
|
16 #include <list>
|
Chris@16
|
17 #endif
|
Chris@16
|
18
|
Chris@16
|
19 #if defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
|
Chris@16
|
20 #include <boost/pool/pool_alloc.hpp>
|
Chris@16
|
21 #endif
|
Chris@16
|
22
|
Chris@16
|
23 #include <algorithm>
|
Chris@16
|
24
|
Chris@16
|
25 #include <boost/ref.hpp>
|
Chris@16
|
26 #include <boost/call_traits.hpp>
|
Chris@16
|
27 #include <boost/spirit/home/classic/namespace.hpp>
|
Chris@16
|
28 #include <boost/spirit/home/classic/core.hpp>
|
Chris@16
|
29 #include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
|
Chris@16
|
30 #include <boost/assert.hpp>
|
Chris@16
|
31
|
Chris@16
|
32 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
33 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
34 #include <iostream>
|
Chris@16
|
35 #include <boost/spirit/home/classic/debug/debug_node.hpp>
|
Chris@16
|
36 #endif
|
Chris@16
|
37
|
Chris@16
|
38 #include <boost/spirit/home/classic/tree/common_fwd.hpp>
|
Chris@16
|
39
|
Chris@16
|
40 namespace boost { namespace spirit {
|
Chris@16
|
41
|
Chris@16
|
42 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
|
Chris@16
|
43
|
Chris@16
|
44 template <typename T>
|
Chris@16
|
45 void swap(tree_node<T>& a, tree_node<T>& b);
|
Chris@16
|
46
|
Chris@16
|
47 template <typename T, typename V>
|
Chris@16
|
48 void swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b);
|
Chris@16
|
49
|
Chris@16
|
50 namespace impl {
|
Chris@16
|
51 template <typename T>
|
Chris@16
|
52 inline void cp_swap(T& t1, T& t2);
|
Chris@16
|
53 }
|
Chris@16
|
54
|
Chris@16
|
55 template <typename T>
|
Chris@16
|
56 struct tree_node
|
Chris@16
|
57 {
|
Chris@16
|
58 typedef T parse_node_t;
|
Chris@16
|
59
|
Chris@16
|
60 #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
|
Chris@16
|
61 typedef std::allocator<tree_node<T> > allocator_type;
|
Chris@16
|
62 #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
63 typedef boost::pool_allocator<tree_node<T> > allocator_type;
|
Chris@16
|
64 #else
|
Chris@16
|
65 typedef boost::fast_pool_allocator<tree_node<T> > allocator_type;
|
Chris@16
|
66 #endif
|
Chris@16
|
67
|
Chris@16
|
68 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
69 typedef std::vector<tree_node<T>, allocator_type> children_t;
|
Chris@16
|
70 #else
|
Chris@16
|
71 typedef std::list<tree_node<T>, allocator_type> children_t;
|
Chris@16
|
72 #endif // BOOST_SPIRIT_USE_LIST_FOR_TREES
|
Chris@16
|
73
|
Chris@16
|
74 typedef typename children_t::iterator tree_iterator;
|
Chris@16
|
75 typedef typename children_t::const_iterator const_tree_iterator;
|
Chris@16
|
76
|
Chris@16
|
77 T value;
|
Chris@16
|
78 children_t children;
|
Chris@16
|
79
|
Chris@16
|
80 tree_node()
|
Chris@16
|
81 : value()
|
Chris@16
|
82 , children()
|
Chris@16
|
83 {}
|
Chris@16
|
84
|
Chris@16
|
85 explicit tree_node(T const& v)
|
Chris@16
|
86 : value(v)
|
Chris@16
|
87 , children()
|
Chris@16
|
88 {}
|
Chris@16
|
89
|
Chris@16
|
90 tree_node(T const& v, children_t const& c)
|
Chris@16
|
91 : value(v)
|
Chris@16
|
92 , children(c)
|
Chris@16
|
93 {}
|
Chris@16
|
94
|
Chris@16
|
95 void swap(tree_node<T>& x)
|
Chris@16
|
96 {
|
Chris@16
|
97 impl::cp_swap(value, x.value);
|
Chris@16
|
98 impl::cp_swap(children, x.children);
|
Chris@16
|
99 }
|
Chris@16
|
100
|
Chris@16
|
101 // Intel V5.0.1 has a problem without this explicit operator=
|
Chris@16
|
102 tree_node &operator= (tree_node const &rhs)
|
Chris@16
|
103 {
|
Chris@16
|
104 tree_node(rhs).swap(*this);
|
Chris@16
|
105 return *this;
|
Chris@16
|
106 }
|
Chris@16
|
107 };
|
Chris@16
|
108
|
Chris@16
|
109 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
110 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
111 template <typename T>
|
Chris@16
|
112 inline std::ostream&
|
Chris@16
|
113 operator<<(std::ostream& o, tree_node<T> const& n)
|
Chris@16
|
114 {
|
Chris@16
|
115 static int depth = 0;
|
Chris@16
|
116 o << "\n";
|
Chris@16
|
117 for (int i = 0; i <= depth; ++i)
|
Chris@16
|
118 {
|
Chris@16
|
119 o << "\t";
|
Chris@16
|
120 }
|
Chris@16
|
121 o << "(depth = " << depth++ << " value = " << n.value;
|
Chris@16
|
122 int c = 0;
|
Chris@16
|
123 for (typename tree_node<T>::children_t::const_iterator it = n.children.begin();
|
Chris@16
|
124 it != n.children.end(); ++it)
|
Chris@16
|
125 {
|
Chris@16
|
126 o << " children[" << c++ << "] = " << *it;
|
Chris@16
|
127 }
|
Chris@16
|
128 o << ")";
|
Chris@16
|
129 --depth;
|
Chris@16
|
130 return o;
|
Chris@16
|
131 }
|
Chris@16
|
132 #endif
|
Chris@16
|
133
|
Chris@16
|
134 //////////////////////////////////
|
Chris@16
|
135 template <typename IteratorT, typename ValueT>
|
Chris@16
|
136 struct node_iter_data
|
Chris@16
|
137 {
|
Chris@16
|
138 typedef IteratorT iterator_t;
|
Chris@16
|
139 typedef IteratorT /*const*/ const_iterator_t;
|
Chris@16
|
140
|
Chris@16
|
141 node_iter_data()
|
Chris@16
|
142 : first(), last(), is_root_(false), parser_id_(), value_()
|
Chris@16
|
143 {}
|
Chris@16
|
144
|
Chris@16
|
145 node_iter_data(IteratorT const& _first, IteratorT const& _last)
|
Chris@16
|
146 : first(_first), last(_last), is_root_(false), parser_id_(), value_()
|
Chris@16
|
147 {}
|
Chris@16
|
148
|
Chris@16
|
149 void swap(node_iter_data& x)
|
Chris@16
|
150 {
|
Chris@16
|
151 impl::cp_swap(first, x.first);
|
Chris@16
|
152 impl::cp_swap(last, x.last);
|
Chris@16
|
153 impl::cp_swap(parser_id_, x.parser_id_);
|
Chris@16
|
154 impl::cp_swap(is_root_, x.is_root_);
|
Chris@16
|
155 impl::cp_swap(value_, x.value_);
|
Chris@16
|
156 }
|
Chris@16
|
157
|
Chris@16
|
158 IteratorT begin()
|
Chris@16
|
159 {
|
Chris@16
|
160 return first;
|
Chris@16
|
161 }
|
Chris@16
|
162
|
Chris@16
|
163 IteratorT const& begin() const
|
Chris@16
|
164 {
|
Chris@16
|
165 return first;
|
Chris@16
|
166 }
|
Chris@16
|
167
|
Chris@16
|
168 IteratorT end()
|
Chris@16
|
169 {
|
Chris@16
|
170 return last;
|
Chris@16
|
171 }
|
Chris@16
|
172
|
Chris@16
|
173 IteratorT const& end() const
|
Chris@16
|
174 {
|
Chris@16
|
175 return last;
|
Chris@16
|
176 }
|
Chris@16
|
177
|
Chris@16
|
178 bool is_root() const
|
Chris@16
|
179 {
|
Chris@16
|
180 return is_root_;
|
Chris@16
|
181 }
|
Chris@16
|
182
|
Chris@16
|
183 void is_root(bool b)
|
Chris@16
|
184 {
|
Chris@16
|
185 is_root_ = b;
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@16
|
188 parser_id id() const
|
Chris@16
|
189 {
|
Chris@16
|
190 return parser_id_;
|
Chris@16
|
191 }
|
Chris@16
|
192
|
Chris@16
|
193 void id(parser_id r)
|
Chris@16
|
194 {
|
Chris@16
|
195 parser_id_ = r;
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198 ValueT const& value() const
|
Chris@16
|
199 {
|
Chris@16
|
200 return value_;
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 void value(ValueT const& v)
|
Chris@16
|
204 {
|
Chris@16
|
205 value_ = v;
|
Chris@16
|
206 }
|
Chris@16
|
207 private:
|
Chris@16
|
208 IteratorT first, last;
|
Chris@16
|
209 bool is_root_;
|
Chris@16
|
210 parser_id parser_id_;
|
Chris@16
|
211 ValueT value_;
|
Chris@16
|
212
|
Chris@16
|
213 public:
|
Chris@16
|
214 };
|
Chris@16
|
215
|
Chris@16
|
216 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
217 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
218 // value is default nil_t, so provide an operator<< for nil_t
|
Chris@16
|
219 inline std::ostream&
|
Chris@16
|
220 operator<<(std::ostream& o, nil_t const&)
|
Chris@16
|
221 {
|
Chris@16
|
222 return o;
|
Chris@16
|
223 }
|
Chris@16
|
224
|
Chris@16
|
225 template <typename IteratorT, typename ValueT>
|
Chris@16
|
226 inline std::ostream&
|
Chris@16
|
227 operator<<(std::ostream& o, node_iter_data<IteratorT, ValueT> const& n)
|
Chris@16
|
228 {
|
Chris@16
|
229 o << "(id = " << n.id() << " text = \"";
|
Chris@16
|
230 typedef typename node_iter_data<IteratorT, ValueT>::const_iterator_t
|
Chris@16
|
231 iterator_t;
|
Chris@16
|
232 for (iterator_t it = n.begin(); it != n.end(); ++it)
|
Chris@16
|
233 impl::token_printer(o, *it);
|
Chris@16
|
234 o << "\" is_root = " << n.is_root()
|
Chris@16
|
235 << /*" value = " << n.value() << */")";
|
Chris@16
|
236 return o;
|
Chris@16
|
237 }
|
Chris@16
|
238 #endif
|
Chris@16
|
239
|
Chris@16
|
240 //////////////////////////////////
|
Chris@16
|
241 template <typename IteratorT = char const*, typename ValueT = nil_t>
|
Chris@16
|
242 struct node_val_data
|
Chris@16
|
243 {
|
Chris@16
|
244 typedef
|
Chris@16
|
245 typename boost::detail::iterator_traits<IteratorT>::value_type
|
Chris@16
|
246 value_type;
|
Chris@16
|
247
|
Chris@16
|
248 #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
|
Chris@16
|
249 typedef std::allocator<value_type> allocator_type;
|
Chris@16
|
250 #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
251 typedef boost::pool_allocator<value_type> allocator_type;
|
Chris@16
|
252 #else
|
Chris@16
|
253 typedef boost::fast_pool_allocator<value_type> allocator_type;
|
Chris@16
|
254 #endif
|
Chris@16
|
255
|
Chris@16
|
256 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
257 typedef std::vector<value_type, allocator_type> container_t;
|
Chris@16
|
258 #else
|
Chris@16
|
259 typedef std::list<value_type, allocator_type> container_t;
|
Chris@16
|
260 #endif
|
Chris@16
|
261
|
Chris@16
|
262 typedef typename container_t::iterator iterator_t;
|
Chris@16
|
263 typedef typename container_t::const_iterator const_iterator_t;
|
Chris@16
|
264
|
Chris@16
|
265 node_val_data()
|
Chris@16
|
266 : text(), is_root_(false), parser_id_(), value_()
|
Chris@16
|
267 {}
|
Chris@16
|
268
|
Chris@16
|
269 #if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
|
Chris@16
|
270 node_val_data(IteratorT const& _first, IteratorT const& _last)
|
Chris@16
|
271 : text(), is_root_(false), parser_id_(), value_()
|
Chris@16
|
272 {
|
Chris@16
|
273 std::copy(_first, _last, std::inserter(text, text.end()));
|
Chris@16
|
274 }
|
Chris@16
|
275
|
Chris@16
|
276 // This constructor is for building text out of iterators
|
Chris@16
|
277 template <typename IteratorT2>
|
Chris@16
|
278 node_val_data(IteratorT2 const& _first, IteratorT2 const& _last)
|
Chris@16
|
279 : text(), is_root_(false), parser_id_(), value_()
|
Chris@16
|
280 {
|
Chris@16
|
281 std::copy(_first, _last, std::inserter(text, text.end()));
|
Chris@16
|
282 }
|
Chris@16
|
283 #else
|
Chris@16
|
284 node_val_data(IteratorT const& _first, IteratorT const& _last)
|
Chris@16
|
285 : text(_first, _last), is_root_(false), parser_id_(), value_()
|
Chris@16
|
286 {}
|
Chris@16
|
287
|
Chris@16
|
288 // This constructor is for building text out of iterators
|
Chris@16
|
289 template <typename IteratorT2>
|
Chris@16
|
290 node_val_data(IteratorT2 const& _first, IteratorT2 const& _last)
|
Chris@16
|
291 : text(_first, _last), is_root_(false), parser_id_(), value_()
|
Chris@16
|
292 {}
|
Chris@16
|
293 #endif
|
Chris@16
|
294
|
Chris@16
|
295 void swap(node_val_data& x)
|
Chris@16
|
296 {
|
Chris@16
|
297 impl::cp_swap(text, x.text);
|
Chris@16
|
298 impl::cp_swap(is_root_, x.is_root_);
|
Chris@16
|
299 impl::cp_swap(parser_id_, x.parser_id_);
|
Chris@16
|
300 impl::cp_swap(value_, x.value_);
|
Chris@16
|
301 }
|
Chris@16
|
302
|
Chris@16
|
303 typename container_t::iterator begin()
|
Chris@16
|
304 {
|
Chris@16
|
305 return text.begin();
|
Chris@16
|
306 }
|
Chris@16
|
307
|
Chris@16
|
308 typename container_t::const_iterator begin() const
|
Chris@16
|
309 {
|
Chris@16
|
310 return text.begin();
|
Chris@16
|
311 }
|
Chris@16
|
312
|
Chris@16
|
313 typename container_t::iterator end()
|
Chris@16
|
314 {
|
Chris@16
|
315 return text.end();
|
Chris@16
|
316 }
|
Chris@16
|
317
|
Chris@16
|
318 typename container_t::const_iterator end() const
|
Chris@16
|
319 {
|
Chris@16
|
320 return text.end();
|
Chris@16
|
321 }
|
Chris@16
|
322
|
Chris@16
|
323 bool is_root() const
|
Chris@16
|
324 {
|
Chris@16
|
325 return is_root_;
|
Chris@16
|
326 }
|
Chris@16
|
327
|
Chris@16
|
328 void is_root(bool b)
|
Chris@16
|
329 {
|
Chris@16
|
330 is_root_ = b;
|
Chris@16
|
331 }
|
Chris@16
|
332
|
Chris@16
|
333 parser_id id() const
|
Chris@16
|
334 {
|
Chris@16
|
335 return parser_id_;
|
Chris@16
|
336 }
|
Chris@16
|
337
|
Chris@16
|
338 void id(parser_id r)
|
Chris@16
|
339 {
|
Chris@16
|
340 parser_id_ = r;
|
Chris@16
|
341 }
|
Chris@16
|
342
|
Chris@16
|
343 ValueT const& value() const
|
Chris@16
|
344 {
|
Chris@16
|
345 return value_;
|
Chris@16
|
346 }
|
Chris@16
|
347
|
Chris@16
|
348 void value(ValueT const& v)
|
Chris@16
|
349 {
|
Chris@16
|
350 value_ = v;
|
Chris@16
|
351 }
|
Chris@16
|
352
|
Chris@16
|
353 private:
|
Chris@16
|
354 container_t text;
|
Chris@16
|
355 bool is_root_;
|
Chris@16
|
356 parser_id parser_id_;
|
Chris@16
|
357 ValueT value_;
|
Chris@16
|
358 };
|
Chris@16
|
359
|
Chris@16
|
360 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
361 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
362 template <typename IteratorT, typename ValueT>
|
Chris@16
|
363 inline std::ostream&
|
Chris@16
|
364 operator<<(std::ostream& o, node_val_data<IteratorT, ValueT> const& n)
|
Chris@16
|
365 {
|
Chris@16
|
366 o << "(id = " << n.id() << " text = \"";
|
Chris@16
|
367 typedef typename node_val_data<IteratorT, ValueT>::const_iterator_t
|
Chris@16
|
368 iterator_t;
|
Chris@16
|
369 for (iterator_t it = n.begin(); it != n.end(); ++it)
|
Chris@16
|
370 impl::token_printer(o, *it);
|
Chris@16
|
371 o << "\" is_root = " << n.is_root()
|
Chris@16
|
372 << " value = " << n.value() << ")";
|
Chris@16
|
373 return o;
|
Chris@16
|
374 }
|
Chris@16
|
375 #endif
|
Chris@16
|
376
|
Chris@16
|
377 template <typename T>
|
Chris@16
|
378 inline void
|
Chris@16
|
379 swap(tree_node<T>& a, tree_node<T>& b)
|
Chris@16
|
380 {
|
Chris@16
|
381 a.swap(b);
|
Chris@16
|
382 }
|
Chris@16
|
383
|
Chris@16
|
384 template <typename T, typename V>
|
Chris@16
|
385 inline void
|
Chris@16
|
386 swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b)
|
Chris@16
|
387 {
|
Chris@16
|
388 a.swap(b);
|
Chris@16
|
389 }
|
Chris@16
|
390
|
Chris@16
|
391 //////////////////////////////////
|
Chris@16
|
392 template <typename ValueT>
|
Chris@16
|
393 class node_iter_data_factory
|
Chris@16
|
394 {
|
Chris@16
|
395 public:
|
Chris@16
|
396 // This inner class is so that node_iter_data_factory can simulate
|
Chris@16
|
397 // a template template parameter
|
Chris@16
|
398 template <typename IteratorT>
|
Chris@16
|
399 class factory
|
Chris@16
|
400 {
|
Chris@16
|
401 public:
|
Chris@16
|
402 typedef IteratorT iterator_t;
|
Chris@16
|
403 typedef node_iter_data<iterator_t, ValueT> node_t;
|
Chris@16
|
404
|
Chris@16
|
405 static node_t create_node(iterator_t const& first, iterator_t const& last,
|
Chris@16
|
406 bool /*is_leaf_node*/)
|
Chris@16
|
407 {
|
Chris@16
|
408 return node_t(first, last);
|
Chris@16
|
409 }
|
Chris@16
|
410
|
Chris@16
|
411 static node_t empty_node()
|
Chris@16
|
412 {
|
Chris@16
|
413 return node_t();
|
Chris@16
|
414 }
|
Chris@16
|
415
|
Chris@16
|
416 // precondition: ContainerT contains a tree_node<node_t>. And all
|
Chris@16
|
417 // iterators in the container point to the same sequence.
|
Chris@16
|
418 template <typename ContainerT>
|
Chris@16
|
419 static node_t group_nodes(ContainerT const& nodes)
|
Chris@16
|
420 {
|
Chris@16
|
421 return node_t(nodes.begin()->value.begin(),
|
Chris@16
|
422 nodes.back().value.end());
|
Chris@16
|
423 }
|
Chris@16
|
424 };
|
Chris@16
|
425 };
|
Chris@16
|
426
|
Chris@16
|
427 //////////////////////////////////
|
Chris@16
|
428 template <typename ValueT>
|
Chris@16
|
429 class node_val_data_factory
|
Chris@16
|
430 {
|
Chris@16
|
431 public:
|
Chris@16
|
432 // This inner class is so that node_val_data_factory can simulate
|
Chris@16
|
433 // a template template parameter
|
Chris@16
|
434 template <typename IteratorT>
|
Chris@16
|
435 class factory
|
Chris@16
|
436 {
|
Chris@16
|
437 public:
|
Chris@16
|
438 typedef IteratorT iterator_t;
|
Chris@16
|
439 typedef node_val_data<iterator_t, ValueT> node_t;
|
Chris@16
|
440
|
Chris@16
|
441 static node_t create_node(iterator_t const& first, iterator_t const& last,
|
Chris@16
|
442 bool is_leaf_node)
|
Chris@16
|
443 {
|
Chris@16
|
444 if (is_leaf_node)
|
Chris@16
|
445 return node_t(first, last);
|
Chris@16
|
446 else
|
Chris@16
|
447 return node_t();
|
Chris@16
|
448 }
|
Chris@16
|
449
|
Chris@16
|
450 static node_t empty_node()
|
Chris@16
|
451 {
|
Chris@16
|
452 return node_t();
|
Chris@16
|
453 }
|
Chris@16
|
454
|
Chris@16
|
455 template <typename ContainerT>
|
Chris@16
|
456 static node_t group_nodes(ContainerT const& nodes)
|
Chris@16
|
457 {
|
Chris@16
|
458 typename node_t::container_t c;
|
Chris@16
|
459 typename ContainerT::const_iterator i_end = nodes.end();
|
Chris@16
|
460 // copy all the nodes text into a new one
|
Chris@16
|
461 for (typename ContainerT::const_iterator i = nodes.begin();
|
Chris@16
|
462 i != i_end; ++i)
|
Chris@16
|
463 {
|
Chris@16
|
464 // See docs: reduced_node_d cannot be used with a
|
Chris@16
|
465 // rule inside the [].
|
Chris@16
|
466 BOOST_ASSERT(i->children.size() == 0);
|
Chris@16
|
467 c.insert(c.end(), i->value.begin(), i->value.end());
|
Chris@16
|
468 }
|
Chris@16
|
469 return node_t(c.begin(), c.end());
|
Chris@16
|
470 }
|
Chris@16
|
471 };
|
Chris@16
|
472 };
|
Chris@16
|
473
|
Chris@16
|
474 //////////////////////////////////
|
Chris@16
|
475 template <typename ValueT>
|
Chris@16
|
476 class node_all_val_data_factory
|
Chris@16
|
477 {
|
Chris@16
|
478 public:
|
Chris@16
|
479 // This inner class is so that node_all_val_data_factory can simulate
|
Chris@16
|
480 // a template template parameter
|
Chris@16
|
481 template <typename IteratorT>
|
Chris@16
|
482 class factory
|
Chris@16
|
483 {
|
Chris@16
|
484 public:
|
Chris@16
|
485 typedef IteratorT iterator_t;
|
Chris@16
|
486 typedef node_val_data<iterator_t, ValueT> node_t;
|
Chris@16
|
487
|
Chris@16
|
488 static node_t create_node(iterator_t const& first, iterator_t const& last,
|
Chris@16
|
489 bool /*is_leaf_node*/)
|
Chris@16
|
490 {
|
Chris@16
|
491 return node_t(first, last);
|
Chris@16
|
492 }
|
Chris@16
|
493
|
Chris@16
|
494 static node_t empty_node()
|
Chris@16
|
495 {
|
Chris@16
|
496 return node_t();
|
Chris@16
|
497 }
|
Chris@16
|
498
|
Chris@16
|
499 template <typename ContainerT>
|
Chris@16
|
500 static node_t group_nodes(ContainerT const& nodes)
|
Chris@16
|
501 {
|
Chris@16
|
502 typename node_t::container_t c;
|
Chris@16
|
503 typename ContainerT::const_iterator i_end = nodes.end();
|
Chris@16
|
504 // copy all the nodes text into a new one
|
Chris@16
|
505 for (typename ContainerT::const_iterator i = nodes.begin();
|
Chris@16
|
506 i != i_end; ++i)
|
Chris@16
|
507 {
|
Chris@16
|
508 BOOST_ASSERT(i->children.size() == 0);
|
Chris@16
|
509 c.insert(c.end(), i->value.begin(), i->value.end());
|
Chris@16
|
510 }
|
Chris@16
|
511 return node_t(c.begin(), c.end());
|
Chris@16
|
512 }
|
Chris@16
|
513 };
|
Chris@16
|
514 };
|
Chris@16
|
515
|
Chris@16
|
516 namespace impl {
|
Chris@16
|
517
|
Chris@16
|
518 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
519 // can't call unqualified swap from within classname::swap
|
Chris@16
|
520 // as Koenig lookup rules will find only the classname::swap
|
Chris@16
|
521 // member function not the global declaration, so use cp_swap
|
Chris@16
|
522 // as a forwarding function (JM):
|
Chris@16
|
523 #if __GNUC__ == 2
|
Chris@16
|
524 using ::std::swap;
|
Chris@16
|
525 #endif
|
Chris@16
|
526 template <typename T>
|
Chris@16
|
527 inline void cp_swap(T& t1, T& t2)
|
Chris@16
|
528 {
|
Chris@16
|
529 using std::swap;
|
Chris@16
|
530 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
531 using boost::swap;
|
Chris@16
|
532 swap(t1, t2);
|
Chris@16
|
533 }
|
Chris@16
|
534 }
|
Chris@16
|
535
|
Chris@16
|
536 //////////////////////////////////
|
Chris@16
|
537 template <typename IteratorT, typename NodeFactoryT, typename T>
|
Chris@16
|
538 class tree_match : public match<T>
|
Chris@16
|
539 {
|
Chris@16
|
540 public:
|
Chris@16
|
541
|
Chris@16
|
542 typedef typename NodeFactoryT::template factory<IteratorT> node_factory_t;
|
Chris@16
|
543 typedef typename node_factory_t::node_t parse_node_t;
|
Chris@16
|
544 typedef tree_node<parse_node_t> node_t;
|
Chris@16
|
545 typedef typename node_t::children_t container_t;
|
Chris@16
|
546 typedef typename container_t::iterator tree_iterator;
|
Chris@16
|
547 typedef typename container_t::const_iterator const_tree_iterator;
|
Chris@16
|
548
|
Chris@16
|
549 typedef T attr_t;
|
Chris@16
|
550 typedef typename boost::call_traits<T>::param_type param_type;
|
Chris@16
|
551 typedef typename boost::call_traits<T>::reference reference;
|
Chris@16
|
552 typedef typename boost::call_traits<T>::const_reference const_reference;
|
Chris@16
|
553
|
Chris@16
|
554 tree_match()
|
Chris@16
|
555 : match<T>(), trees()
|
Chris@16
|
556 {}
|
Chris@16
|
557
|
Chris@16
|
558 explicit
|
Chris@16
|
559 tree_match(std::size_t length_)
|
Chris@16
|
560 : match<T>(length_), trees()
|
Chris@16
|
561 {}
|
Chris@16
|
562
|
Chris@16
|
563 tree_match(std::size_t length_, parse_node_t const& n)
|
Chris@16
|
564 : match<T>(length_), trees()
|
Chris@16
|
565 {
|
Chris@16
|
566 trees.push_back(node_t(n));
|
Chris@16
|
567 }
|
Chris@16
|
568
|
Chris@16
|
569 tree_match(std::size_t length_, param_type val, parse_node_t const& n)
|
Chris@16
|
570 : match<T>(length_, val), trees()
|
Chris@16
|
571 {
|
Chris@16
|
572 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
573 trees.reserve(10); // this is more or less an arbitrary number...
|
Chris@16
|
574 #endif
|
Chris@16
|
575 trees.push_back(node_t(n));
|
Chris@16
|
576 }
|
Chris@16
|
577
|
Chris@16
|
578 // attention, these constructors will change the second parameter!
|
Chris@16
|
579 tree_match(std::size_t length_, container_t& c)
|
Chris@16
|
580 : match<T>(length_), trees()
|
Chris@16
|
581 {
|
Chris@16
|
582 impl::cp_swap(trees, c);
|
Chris@16
|
583 }
|
Chris@16
|
584
|
Chris@16
|
585 tree_match(std::size_t length_, param_type val, container_t& c)
|
Chris@16
|
586 : match<T>(length_, val), trees()
|
Chris@16
|
587 {
|
Chris@16
|
588 impl::cp_swap(trees, c);
|
Chris@16
|
589 }
|
Chris@16
|
590
|
Chris@16
|
591 template <typename T2>
|
Chris@16
|
592 tree_match(match<T2> const& other)
|
Chris@16
|
593 : match<T>(other), trees()
|
Chris@16
|
594 {}
|
Chris@16
|
595
|
Chris@16
|
596 template <typename T2, typename T3, typename T4>
|
Chris@16
|
597 tree_match(tree_match<T2, T3, T4> const& other)
|
Chris@16
|
598 : match<T>(other), trees()
|
Chris@16
|
599 { impl::cp_swap(trees, other.trees); }
|
Chris@16
|
600
|
Chris@16
|
601 template <typename T2>
|
Chris@16
|
602 tree_match&
|
Chris@16
|
603 operator=(match<T2> const& other)
|
Chris@16
|
604 {
|
Chris@16
|
605 match<T>::operator=(other);
|
Chris@16
|
606 return *this;
|
Chris@16
|
607 }
|
Chris@16
|
608
|
Chris@16
|
609 template <typename T2, typename T3, typename T4>
|
Chris@16
|
610 tree_match&
|
Chris@16
|
611 operator=(tree_match<T2, T3, T4> const& other)
|
Chris@16
|
612 {
|
Chris@16
|
613 match<T>::operator=(other);
|
Chris@16
|
614 impl::cp_swap(trees, other.trees);
|
Chris@16
|
615 return *this;
|
Chris@16
|
616 }
|
Chris@16
|
617
|
Chris@16
|
618 tree_match(tree_match const& x)
|
Chris@16
|
619 : match<T>(x), trees()
|
Chris@16
|
620 {
|
Chris@16
|
621 // use auto_ptr like ownership for the trees data member
|
Chris@16
|
622 impl::cp_swap(trees, x.trees);
|
Chris@16
|
623 }
|
Chris@16
|
624
|
Chris@16
|
625 tree_match& operator=(tree_match const& x)
|
Chris@16
|
626 {
|
Chris@16
|
627 tree_match tmp(x);
|
Chris@16
|
628 this->swap(tmp);
|
Chris@16
|
629 return *this;
|
Chris@16
|
630 }
|
Chris@16
|
631
|
Chris@16
|
632 void swap(tree_match& x)
|
Chris@16
|
633 {
|
Chris@16
|
634 match<T>::swap(x);
|
Chris@16
|
635 impl::cp_swap(trees, x.trees);
|
Chris@16
|
636 }
|
Chris@16
|
637
|
Chris@16
|
638 mutable container_t trees;
|
Chris@16
|
639 };
|
Chris@16
|
640
|
Chris@16
|
641 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
642 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
643 template <typename IteratorT, typename NodeFactoryT, typename T>
|
Chris@16
|
644 inline std::ostream&
|
Chris@16
|
645 operator<<(std::ostream& o, tree_match<IteratorT, NodeFactoryT, T> const& m)
|
Chris@16
|
646 {
|
Chris@16
|
647 typedef
|
Chris@16
|
648 typename tree_match<IteratorT, NodeFactoryT, T>::container_t::iterator
|
Chris@16
|
649 iterator;
|
Chris@16
|
650
|
Chris@16
|
651 o << "(length = " << (int)m.length();
|
Chris@16
|
652 int c = 0;
|
Chris@16
|
653 for (iterator i = m.trees.begin(); i != m.trees.end(); ++i)
|
Chris@16
|
654 {
|
Chris@16
|
655 o << " trees[" << c++ << "] = " << *i;
|
Chris@16
|
656 }
|
Chris@16
|
657 o << "\n)";
|
Chris@16
|
658 return o;
|
Chris@16
|
659 }
|
Chris@16
|
660 #endif
|
Chris@16
|
661
|
Chris@16
|
662 //////////////////////////////////
|
Chris@16
|
663 struct tree_policy
|
Chris@16
|
664 {
|
Chris@16
|
665 template <typename FunctorT, typename MatchT>
|
Chris@16
|
666 static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/)
|
Chris@16
|
667 {}
|
Chris@16
|
668
|
Chris@16
|
669 template <typename MatchT, typename Iterator1T, typename Iterator2T>
|
Chris@16
|
670 static void group_match(MatchT& /*m*/, parser_id const& /*id*/,
|
Chris@16
|
671 Iterator1T const& /*first*/, Iterator2T const& /*last*/)
|
Chris@16
|
672 {}
|
Chris@16
|
673
|
Chris@16
|
674 template <typename MatchT>
|
Chris@16
|
675 static void concat(MatchT& /*a*/, MatchT const& /*b*/)
|
Chris@16
|
676 {}
|
Chris@16
|
677 };
|
Chris@16
|
678
|
Chris@16
|
679 //////////////////////////////////
|
Chris@16
|
680 template <
|
Chris@16
|
681 typename MatchPolicyT,
|
Chris@16
|
682 typename IteratorT,
|
Chris@16
|
683 typename NodeFactoryT,
|
Chris@16
|
684 typename TreePolicyT,
|
Chris@16
|
685 typename T
|
Chris@16
|
686 >
|
Chris@16
|
687 struct common_tree_match_policy : public match_policy
|
Chris@16
|
688 {
|
Chris@16
|
689 common_tree_match_policy()
|
Chris@16
|
690 {
|
Chris@16
|
691 }
|
Chris@16
|
692
|
Chris@16
|
693 template <typename PolicyT>
|
Chris@16
|
694 common_tree_match_policy(PolicyT const & policies)
|
Chris@16
|
695 : match_policy((match_policy const &)policies)
|
Chris@16
|
696 {
|
Chris@16
|
697 }
|
Chris@16
|
698
|
Chris@16
|
699 template <typename U>
|
Chris@16
|
700 struct result { typedef tree_match<IteratorT, NodeFactoryT, U> type; };
|
Chris@16
|
701
|
Chris@16
|
702 typedef tree_match<IteratorT, NodeFactoryT, T> match_t;
|
Chris@16
|
703 typedef IteratorT iterator_t;
|
Chris@16
|
704 typedef TreePolicyT tree_policy_t;
|
Chris@16
|
705 typedef NodeFactoryT factory_t;
|
Chris@16
|
706
|
Chris@16
|
707 static const match_t no_match() { return match_t(); }
|
Chris@16
|
708 static const match_t empty_match()
|
Chris@16
|
709 { return match_t(0, tree_policy_t::empty_node()); }
|
Chris@16
|
710
|
Chris@16
|
711 template <typename AttrT, typename Iterator1T, typename Iterator2T>
|
Chris@16
|
712 static tree_match<IteratorT, NodeFactoryT, AttrT> create_match(
|
Chris@16
|
713 std::size_t length,
|
Chris@16
|
714 AttrT const& val,
|
Chris@16
|
715 Iterator1T const& first,
|
Chris@16
|
716 Iterator2T const& last)
|
Chris@16
|
717 {
|
Chris@16
|
718 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
719 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
720
|
Chris@16
|
721 BOOST_SPIRIT_DEBUG_OUT << "\n>>> create_node(begin) <<<\n"
|
Chris@16
|
722 "creating node text: \"";
|
Chris@16
|
723 for (Iterator1T it = first; it != last; ++it)
|
Chris@16
|
724 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
|
Chris@16
|
725 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
|
Chris@16
|
726 BOOST_SPIRIT_DEBUG_OUT << ">>> create_node(end) <<<\n\n";
|
Chris@16
|
727 #endif
|
Chris@16
|
728 return tree_match<IteratorT, NodeFactoryT, AttrT>(length, val,
|
Chris@16
|
729 tree_policy_t::create_node(length, first, last, true));
|
Chris@16
|
730 }
|
Chris@16
|
731
|
Chris@16
|
732 template <typename Match1T, typename Match2T>
|
Chris@16
|
733 static void concat_match(Match1T& a, Match2T const& b)
|
Chris@16
|
734 {
|
Chris@16
|
735 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
736 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
737
|
Chris@16
|
738 BOOST_SPIRIT_DEBUG_OUT << "\n>>> concat_match(begin) <<<\n";
|
Chris@16
|
739 BOOST_SPIRIT_DEBUG_OUT << "tree a:\n" << a << "\n";
|
Chris@16
|
740 BOOST_SPIRIT_DEBUG_OUT << "tree b:\n" << b << "\n";
|
Chris@16
|
741 BOOST_SPIRIT_DEBUG_OUT << ">>> concat_match(end) <<<\n\n";
|
Chris@16
|
742 #endif
|
Chris@16
|
743 BOOST_SPIRIT_ASSERT(a && b);
|
Chris@16
|
744 if (a.length() == 0)
|
Chris@16
|
745 {
|
Chris@16
|
746 a = b;
|
Chris@16
|
747 return;
|
Chris@16
|
748 }
|
Chris@16
|
749 else if (b.length() == 0
|
Chris@16
|
750 #ifdef BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING
|
Chris@16
|
751 && !b.trees.begin()->value.id().to_long()
|
Chris@16
|
752 #endif
|
Chris@16
|
753 )
|
Chris@16
|
754 {
|
Chris@16
|
755 return;
|
Chris@16
|
756 }
|
Chris@16
|
757 a.concat(b);
|
Chris@16
|
758 tree_policy_t::concat(a, b);
|
Chris@16
|
759 }
|
Chris@16
|
760
|
Chris@16
|
761 template <typename MatchT, typename IteratorT2>
|
Chris@16
|
762 void
|
Chris@16
|
763 group_match(
|
Chris@16
|
764 MatchT& m,
|
Chris@16
|
765 parser_id const& id,
|
Chris@16
|
766 IteratorT2 const& first,
|
Chris@16
|
767 IteratorT2 const& last) const
|
Chris@16
|
768 {
|
Chris@16
|
769 if (!m) return;
|
Chris@16
|
770
|
Chris@16
|
771 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
772 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_TREES)
|
Chris@16
|
773
|
Chris@16
|
774 BOOST_SPIRIT_DEBUG_OUT << "\n>>> group_match(begin) <<<\n"
|
Chris@16
|
775 "new node(" << id << ") \"";
|
Chris@16
|
776 for (IteratorT2 it = first; it != last; ++it)
|
Chris@16
|
777 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
|
Chris@16
|
778 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
|
Chris@16
|
779 BOOST_SPIRIT_DEBUG_OUT << "new child tree (before grouping):\n" << m << "\n";
|
Chris@16
|
780
|
Chris@16
|
781 tree_policy_t::group_match(m, id, first, last);
|
Chris@16
|
782
|
Chris@16
|
783 BOOST_SPIRIT_DEBUG_OUT << "new child tree (after grouping):\n" << m << "\n";
|
Chris@16
|
784 BOOST_SPIRIT_DEBUG_OUT << ">>> group_match(end) <<<\n\n";
|
Chris@16
|
785 #else
|
Chris@16
|
786 tree_policy_t::group_match(m, id, first, last);
|
Chris@16
|
787 #endif
|
Chris@16
|
788 }
|
Chris@16
|
789 };
|
Chris@16
|
790
|
Chris@16
|
791 //////////////////////////////////
|
Chris@16
|
792 template <typename MatchPolicyT, typename NodeFactoryT>
|
Chris@16
|
793 struct common_tree_tree_policy
|
Chris@16
|
794 {
|
Chris@16
|
795 typedef typename MatchPolicyT::iterator_t iterator_t;
|
Chris@16
|
796 typedef typename MatchPolicyT::match_t match_t;
|
Chris@16
|
797 typedef typename NodeFactoryT::template factory<iterator_t> factory_t;
|
Chris@16
|
798 typedef typename factory_t::node_t node_t;
|
Chris@16
|
799
|
Chris@16
|
800 template <typename Iterator1T, typename Iterator2T>
|
Chris@16
|
801 static node_t
|
Chris@16
|
802 create_node(std::size_t /*length*/, Iterator1T const& first,
|
Chris@16
|
803 Iterator2T const& last, bool leaf_node)
|
Chris@16
|
804 {
|
Chris@16
|
805 return factory_t::create_node(first, last, leaf_node);
|
Chris@16
|
806 }
|
Chris@16
|
807
|
Chris@16
|
808 static node_t
|
Chris@16
|
809 empty_node()
|
Chris@16
|
810 {
|
Chris@16
|
811 return factory_t::empty_node();
|
Chris@16
|
812 }
|
Chris@16
|
813
|
Chris@16
|
814 template <typename FunctorT>
|
Chris@16
|
815 static void apply_op_to_match(FunctorT const& op, match_t& m)
|
Chris@16
|
816 {
|
Chris@16
|
817 op(m);
|
Chris@16
|
818 }
|
Chris@16
|
819 };
|
Chris@16
|
820
|
Chris@16
|
821 //////////////////////////////////
|
Chris@16
|
822 // directives to modify how the parse tree is generated
|
Chris@16
|
823
|
Chris@16
|
824 struct no_tree_gen_node_parser_gen;
|
Chris@16
|
825
|
Chris@16
|
826 template <typename T>
|
Chris@16
|
827 struct no_tree_gen_node_parser
|
Chris@16
|
828 : public unary<T, parser<no_tree_gen_node_parser<T> > >
|
Chris@16
|
829 {
|
Chris@16
|
830 typedef no_tree_gen_node_parser<T> self_t;
|
Chris@16
|
831 typedef no_tree_gen_node_parser_gen parser_generator_t;
|
Chris@16
|
832 typedef unary_parser_category parser_category_t;
|
Chris@16
|
833
|
Chris@16
|
834 no_tree_gen_node_parser(T const& a)
|
Chris@16
|
835 : unary<T, parser<no_tree_gen_node_parser<T> > >(a) {}
|
Chris@16
|
836
|
Chris@16
|
837 template <typename ScannerT>
|
Chris@16
|
838 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
839 parse(ScannerT const& scanner) const
|
Chris@16
|
840 {
|
Chris@16
|
841 typedef typename ScannerT::iteration_policy_t iteration_policy_t;
|
Chris@16
|
842 typedef match_policy match_policy_t;
|
Chris@16
|
843 typedef typename ScannerT::action_policy_t action_policy_t;
|
Chris@16
|
844 typedef scanner_policies<
|
Chris@16
|
845 iteration_policy_t,
|
Chris@16
|
846 match_policy_t,
|
Chris@16
|
847 action_policy_t
|
Chris@16
|
848 > policies_t;
|
Chris@16
|
849
|
Chris@16
|
850 return this->subject().parse(scanner.change_policies(policies_t(scanner)));
|
Chris@16
|
851 }
|
Chris@16
|
852 };
|
Chris@16
|
853
|
Chris@16
|
854 struct no_tree_gen_node_parser_gen
|
Chris@16
|
855 {
|
Chris@16
|
856 template <typename T>
|
Chris@16
|
857 struct result {
|
Chris@16
|
858
|
Chris@16
|
859 typedef no_tree_gen_node_parser<T> type;
|
Chris@16
|
860 };
|
Chris@16
|
861
|
Chris@16
|
862 template <typename T>
|
Chris@16
|
863 static no_tree_gen_node_parser<T>
|
Chris@16
|
864 generate(parser<T> const& s)
|
Chris@16
|
865 {
|
Chris@16
|
866 return no_tree_gen_node_parser<T>(s.derived());
|
Chris@16
|
867 }
|
Chris@16
|
868
|
Chris@16
|
869 template <typename T>
|
Chris@16
|
870 no_tree_gen_node_parser<T>
|
Chris@16
|
871 operator[](parser<T> const& s) const
|
Chris@16
|
872 {
|
Chris@16
|
873 return no_tree_gen_node_parser<T>(s.derived());
|
Chris@16
|
874 }
|
Chris@16
|
875 };
|
Chris@16
|
876
|
Chris@16
|
877 const no_tree_gen_node_parser_gen no_node_d = no_tree_gen_node_parser_gen();
|
Chris@16
|
878
|
Chris@16
|
879 //////////////////////////////////
|
Chris@16
|
880
|
Chris@16
|
881 struct leaf_node_parser_gen;
|
Chris@16
|
882
|
Chris@16
|
883 template<typename T>
|
Chris@16
|
884 struct leaf_node_parser
|
Chris@16
|
885 : public unary<T, parser<leaf_node_parser<T> > >
|
Chris@16
|
886 {
|
Chris@16
|
887 typedef leaf_node_parser<T> self_t;
|
Chris@16
|
888 typedef leaf_node_parser_gen parser_generator_t;
|
Chris@16
|
889 typedef unary_parser_category parser_category_t;
|
Chris@16
|
890
|
Chris@16
|
891 leaf_node_parser(T const& a)
|
Chris@16
|
892 : unary<T, parser<leaf_node_parser<T> > >(a) {}
|
Chris@16
|
893
|
Chris@16
|
894 template <typename ScannerT>
|
Chris@16
|
895 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
896 parse(ScannerT const& scanner) const
|
Chris@16
|
897 {
|
Chris@16
|
898 typedef scanner_policies< typename ScannerT::iteration_policy_t,
|
Chris@16
|
899 match_policy, typename ScannerT::action_policy_t > policies_t;
|
Chris@16
|
900
|
Chris@16
|
901 typedef typename ScannerT::iterator_t iterator_t;
|
Chris@16
|
902 typedef typename parser_result<self_t, ScannerT>::type result_t;
|
Chris@16
|
903 typedef typename result_t::node_factory_t factory_t;
|
Chris@16
|
904
|
Chris@16
|
905 iterator_t from = scanner.first;
|
Chris@16
|
906 result_t hit = impl::contiguous_parser_parse<result_t>(this->subject(),
|
Chris@16
|
907 scanner.change_policies(policies_t(scanner,match_policy(),scanner)),
|
Chris@16
|
908 scanner);
|
Chris@16
|
909
|
Chris@16
|
910 if (hit)
|
Chris@16
|
911 return result_t(hit.length(),
|
Chris@16
|
912 factory_t::create_node(from, scanner.first, true));
|
Chris@16
|
913 else
|
Chris@16
|
914 return result_t(hit.length());
|
Chris@16
|
915 }
|
Chris@16
|
916 };
|
Chris@16
|
917
|
Chris@16
|
918 struct leaf_node_parser_gen
|
Chris@16
|
919 {
|
Chris@16
|
920 template <typename T>
|
Chris@16
|
921 struct result {
|
Chris@16
|
922
|
Chris@16
|
923 typedef leaf_node_parser<T> type;
|
Chris@16
|
924 };
|
Chris@16
|
925
|
Chris@16
|
926 template <typename T>
|
Chris@16
|
927 static leaf_node_parser<T>
|
Chris@16
|
928 generate(parser<T> const& s)
|
Chris@16
|
929 {
|
Chris@16
|
930 return leaf_node_parser<T>(s.derived());
|
Chris@16
|
931 }
|
Chris@16
|
932
|
Chris@16
|
933 template <typename T>
|
Chris@16
|
934 leaf_node_parser<T>
|
Chris@16
|
935 operator[](parser<T> const& s) const
|
Chris@16
|
936 {
|
Chris@16
|
937 return leaf_node_parser<T>(s.derived());
|
Chris@16
|
938 }
|
Chris@16
|
939 };
|
Chris@16
|
940
|
Chris@16
|
941 const leaf_node_parser_gen leaf_node_d = leaf_node_parser_gen();
|
Chris@16
|
942 const leaf_node_parser_gen token_node_d = leaf_node_parser_gen();
|
Chris@16
|
943
|
Chris@16
|
944 //////////////////////////////////
|
Chris@16
|
945 namespace impl {
|
Chris@16
|
946
|
Chris@16
|
947 template <typename MatchPolicyT>
|
Chris@16
|
948 struct tree_policy_selector
|
Chris@16
|
949 {
|
Chris@16
|
950 typedef tree_policy type;
|
Chris@16
|
951 };
|
Chris@16
|
952
|
Chris@16
|
953 } // namespace impl
|
Chris@16
|
954
|
Chris@16
|
955 //////////////////////////////////
|
Chris@16
|
956 template <typename NodeParserT>
|
Chris@16
|
957 struct node_parser_gen;
|
Chris@16
|
958
|
Chris@16
|
959 template <typename T, typename NodeParserT>
|
Chris@16
|
960 struct node_parser
|
Chris@16
|
961 : public unary<T, parser<node_parser<T, NodeParserT> > >
|
Chris@16
|
962 {
|
Chris@16
|
963 typedef node_parser<T, NodeParserT> self_t;
|
Chris@16
|
964 typedef node_parser_gen<NodeParserT> parser_generator_t;
|
Chris@16
|
965 typedef unary_parser_category parser_category_t;
|
Chris@16
|
966
|
Chris@16
|
967 node_parser(T const& a)
|
Chris@16
|
968 : unary<T, parser<node_parser<T, NodeParserT> > >(a) {}
|
Chris@16
|
969
|
Chris@16
|
970 template <typename ScannerT>
|
Chris@16
|
971 struct result
|
Chris@16
|
972 {
|
Chris@16
|
973 typedef typename parser_result<T, ScannerT>::type type;
|
Chris@16
|
974 };
|
Chris@16
|
975
|
Chris@16
|
976 template <typename ScannerT>
|
Chris@16
|
977 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
978 parse(ScannerT const& scanner) const
|
Chris@16
|
979 {
|
Chris@16
|
980 typename parser_result<self_t, ScannerT>::type hit = this->subject().parse(scanner);
|
Chris@16
|
981 if (hit)
|
Chris@16
|
982 {
|
Chris@16
|
983 impl::tree_policy_selector<typename ScannerT::match_policy_t>::type::apply_op_to_match(NodeParserT(), hit);
|
Chris@16
|
984 }
|
Chris@16
|
985 return hit;
|
Chris@16
|
986 }
|
Chris@16
|
987 };
|
Chris@16
|
988
|
Chris@16
|
989 template <typename NodeParserT>
|
Chris@16
|
990 struct node_parser_gen
|
Chris@16
|
991 {
|
Chris@16
|
992 template <typename T>
|
Chris@16
|
993 struct result {
|
Chris@16
|
994
|
Chris@16
|
995 typedef node_parser<T, NodeParserT> type;
|
Chris@16
|
996 };
|
Chris@16
|
997
|
Chris@16
|
998 template <typename T>
|
Chris@16
|
999 static node_parser<T, NodeParserT>
|
Chris@16
|
1000 generate(parser<T> const& s)
|
Chris@16
|
1001 {
|
Chris@16
|
1002 return node_parser<T, NodeParserT>(s.derived());
|
Chris@16
|
1003 }
|
Chris@16
|
1004
|
Chris@16
|
1005 template <typename T>
|
Chris@16
|
1006 node_parser<T, NodeParserT>
|
Chris@16
|
1007 operator[](parser<T> const& s) const
|
Chris@16
|
1008 {
|
Chris@16
|
1009 return node_parser<T, NodeParserT>(s.derived());
|
Chris@16
|
1010 }
|
Chris@16
|
1011 };
|
Chris@16
|
1012 //////////////////////////////////
|
Chris@16
|
1013 struct reduced_node_op
|
Chris@16
|
1014 {
|
Chris@16
|
1015 template <typename MatchT>
|
Chris@16
|
1016 void operator()(MatchT& m) const
|
Chris@16
|
1017 {
|
Chris@16
|
1018 if (m.trees.size() == 1)
|
Chris@16
|
1019 {
|
Chris@16
|
1020 m.trees.begin()->children.clear();
|
Chris@16
|
1021 }
|
Chris@16
|
1022 else if (m.trees.size() > 1)
|
Chris@16
|
1023 {
|
Chris@16
|
1024 typedef typename MatchT::node_factory_t node_factory_t;
|
Chris@16
|
1025 m = MatchT(m.length(), node_factory_t::group_nodes(m.trees));
|
Chris@16
|
1026 }
|
Chris@16
|
1027 }
|
Chris@16
|
1028 };
|
Chris@16
|
1029
|
Chris@16
|
1030 const node_parser_gen<reduced_node_op> reduced_node_d =
|
Chris@16
|
1031 node_parser_gen<reduced_node_op>();
|
Chris@16
|
1032
|
Chris@16
|
1033
|
Chris@16
|
1034 struct discard_node_op
|
Chris@16
|
1035 {
|
Chris@16
|
1036 template <typename MatchT>
|
Chris@16
|
1037 void operator()(MatchT& m) const
|
Chris@16
|
1038 {
|
Chris@16
|
1039 m.trees.clear();
|
Chris@16
|
1040 }
|
Chris@16
|
1041 };
|
Chris@16
|
1042
|
Chris@16
|
1043 const node_parser_gen<discard_node_op> discard_node_d =
|
Chris@16
|
1044 node_parser_gen<discard_node_op>();
|
Chris@16
|
1045
|
Chris@16
|
1046 struct infix_node_op
|
Chris@16
|
1047 {
|
Chris@16
|
1048 template <typename MatchT>
|
Chris@16
|
1049 void operator()(MatchT& m) const
|
Chris@16
|
1050 {
|
Chris@16
|
1051 typedef typename MatchT::container_t container_t;
|
Chris@16
|
1052 typedef typename MatchT::container_t::iterator iter_t;
|
Chris@16
|
1053 typedef typename MatchT::container_t::value_type value_t;
|
Chris@16
|
1054
|
Chris@16
|
1055 using std::swap;
|
Chris@16
|
1056 using boost::swap;
|
Chris@16
|
1057 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1058
|
Chris@16
|
1059 // copying the tree nodes is expensive, since it may copy a whole
|
Chris@16
|
1060 // tree. swapping them is cheap, so swap the nodes we want into
|
Chris@16
|
1061 // a new container of children.
|
Chris@16
|
1062 container_t new_children;
|
Chris@16
|
1063 std::size_t length = 0;
|
Chris@16
|
1064 std::size_t tree_size = m.trees.size();
|
Chris@16
|
1065
|
Chris@16
|
1066 // the infix_node_d[] make no sense for nodes with no subnodes
|
Chris@16
|
1067 BOOST_SPIRIT_ASSERT(tree_size >= 1);
|
Chris@16
|
1068
|
Chris@16
|
1069 bool keep = true;
|
Chris@16
|
1070 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
1071 new_children.reserve((tree_size+1)/2);
|
Chris@16
|
1072 #endif
|
Chris@16
|
1073 iter_t i_end = m.trees.end();
|
Chris@16
|
1074 for (iter_t i = m.trees.begin(); i != i_end; ++i)
|
Chris@16
|
1075 {
|
Chris@16
|
1076 if (keep) {
|
Chris@16
|
1077 // adjust the length
|
Chris@16
|
1078 length += std::distance((*i).value.begin(), (*i).value.end());
|
Chris@16
|
1079
|
Chris@16
|
1080 // move the child node
|
Chris@16
|
1081 new_children.push_back(value_t());
|
Chris@16
|
1082 swap(new_children.back(), *i);
|
Chris@16
|
1083 keep = false;
|
Chris@16
|
1084 }
|
Chris@16
|
1085 else {
|
Chris@16
|
1086 // ignore this child node
|
Chris@16
|
1087 keep = true;
|
Chris@16
|
1088 }
|
Chris@16
|
1089 }
|
Chris@16
|
1090
|
Chris@16
|
1091 m = MatchT(length, new_children);
|
Chris@16
|
1092 }
|
Chris@16
|
1093 };
|
Chris@16
|
1094
|
Chris@16
|
1095 const node_parser_gen<infix_node_op> infix_node_d =
|
Chris@16
|
1096 node_parser_gen<infix_node_op>();
|
Chris@16
|
1097
|
Chris@16
|
1098 struct discard_first_node_op
|
Chris@16
|
1099 {
|
Chris@16
|
1100 template <typename MatchT>
|
Chris@16
|
1101 void operator()(MatchT& m) const
|
Chris@16
|
1102 {
|
Chris@16
|
1103 typedef typename MatchT::container_t container_t;
|
Chris@16
|
1104 typedef typename MatchT::container_t::iterator iter_t;
|
Chris@16
|
1105 typedef typename MatchT::container_t::value_type value_t;
|
Chris@16
|
1106
|
Chris@16
|
1107 using std::swap;
|
Chris@16
|
1108 using boost::swap;
|
Chris@16
|
1109 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1110
|
Chris@16
|
1111 // copying the tree nodes is expensive, since it may copy a whole
|
Chris@16
|
1112 // tree. swapping them is cheap, so swap the nodes we want into
|
Chris@16
|
1113 // a new container of children, instead of saying
|
Chris@16
|
1114 // m.trees.erase(m.trees.begin()) because, on a container_t that will
|
Chris@16
|
1115 // cause all the nodes afterwards to be copied into the previous
|
Chris@16
|
1116 // position.
|
Chris@16
|
1117 container_t new_children;
|
Chris@16
|
1118 std::size_t length = 0;
|
Chris@16
|
1119 std::size_t tree_size = m.trees.size();
|
Chris@16
|
1120
|
Chris@16
|
1121 // the discard_first_node_d[] make no sense for nodes with no subnodes
|
Chris@16
|
1122 BOOST_SPIRIT_ASSERT(tree_size >= 1);
|
Chris@16
|
1123
|
Chris@16
|
1124 if (tree_size > 1) {
|
Chris@16
|
1125 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
1126 new_children.reserve(tree_size - 1);
|
Chris@16
|
1127 #endif
|
Chris@16
|
1128 iter_t i = m.trees.begin(), i_end = m.trees.end();
|
Chris@16
|
1129 for (++i; i != i_end; ++i)
|
Chris@16
|
1130 {
|
Chris@16
|
1131 // adjust the length
|
Chris@16
|
1132 length += std::distance((*i).value.begin(), (*i).value.end());
|
Chris@16
|
1133
|
Chris@16
|
1134 // move the child node
|
Chris@16
|
1135 new_children.push_back(value_t());
|
Chris@16
|
1136 swap(new_children.back(), *i);
|
Chris@16
|
1137 }
|
Chris@16
|
1138 }
|
Chris@16
|
1139 else {
|
Chris@16
|
1140 // if there was a tree and now there isn't any, insert an empty node
|
Chris@16
|
1141 iter_t i = m.trees.begin();
|
Chris@16
|
1142
|
Chris@16
|
1143 // This isn't entirely correct, since the empty node will reference
|
Chris@16
|
1144 // the end of the discarded node, but I currently don't see any way to
|
Chris@16
|
1145 // get at the begin of the node following this subnode.
|
Chris@16
|
1146 // This should be safe anyway because the it shouldn't get dereferenced
|
Chris@16
|
1147 // under any circumstances.
|
Chris@16
|
1148 typedef typename value_t::parse_node_t::iterator_t iterator_type;
|
Chris@16
|
1149 iterator_type it = (*i).value.end();
|
Chris@16
|
1150
|
Chris@16
|
1151 new_children.push_back(
|
Chris@16
|
1152 value_t(typename value_t::parse_node_t(it, it)));
|
Chris@16
|
1153 }
|
Chris@16
|
1154
|
Chris@16
|
1155 m = MatchT(length, new_children);
|
Chris@16
|
1156 }
|
Chris@16
|
1157 };
|
Chris@16
|
1158
|
Chris@16
|
1159 const node_parser_gen<discard_first_node_op> discard_first_node_d =
|
Chris@16
|
1160 node_parser_gen<discard_first_node_op>();
|
Chris@16
|
1161
|
Chris@16
|
1162 struct discard_last_node_op
|
Chris@16
|
1163 {
|
Chris@16
|
1164 template <typename MatchT>
|
Chris@16
|
1165 void operator()(MatchT& m) const
|
Chris@16
|
1166 {
|
Chris@16
|
1167 typedef typename MatchT::container_t container_t;
|
Chris@16
|
1168 typedef typename MatchT::container_t::iterator iter_t;
|
Chris@16
|
1169 typedef typename MatchT::container_t::value_type value_t;
|
Chris@16
|
1170
|
Chris@16
|
1171 using std::swap;
|
Chris@16
|
1172 using boost::swap;
|
Chris@16
|
1173 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1174
|
Chris@16
|
1175 // copying the tree nodes is expensive, since it may copy a whole
|
Chris@16
|
1176 // tree. swapping them is cheap, so swap the nodes we want into
|
Chris@16
|
1177 // a new container of children, instead of saying
|
Chris@16
|
1178 // m.trees.erase(m.trees.begin()) because, on a container_t that will
|
Chris@16
|
1179 // cause all the nodes afterwards to be copied into the previous
|
Chris@16
|
1180 // position.
|
Chris@16
|
1181 container_t new_children;
|
Chris@16
|
1182 std::size_t length = 0;
|
Chris@16
|
1183 std::size_t tree_size = m.trees.size();
|
Chris@16
|
1184
|
Chris@16
|
1185 // the discard_last_node_d[] make no sense for nodes with no subnodes
|
Chris@16
|
1186 BOOST_SPIRIT_ASSERT(tree_size >= 1);
|
Chris@16
|
1187
|
Chris@16
|
1188 if (tree_size > 1) {
|
Chris@16
|
1189 m.trees.pop_back();
|
Chris@16
|
1190 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
1191 new_children.reserve(tree_size - 1);
|
Chris@16
|
1192 #endif
|
Chris@16
|
1193 iter_t i_end = m.trees.end();
|
Chris@16
|
1194 for (iter_t i = m.trees.begin(); i != i_end; ++i)
|
Chris@16
|
1195 {
|
Chris@16
|
1196 // adjust the length
|
Chris@16
|
1197 length += std::distance((*i).value.begin(), (*i).value.end());
|
Chris@16
|
1198
|
Chris@16
|
1199 // move the child node
|
Chris@16
|
1200 new_children.push_back(value_t());
|
Chris@16
|
1201 swap(new_children.back(), *i);
|
Chris@16
|
1202 }
|
Chris@16
|
1203 }
|
Chris@16
|
1204 else {
|
Chris@16
|
1205 // if there was a tree and now there isn't any, insert an empty node
|
Chris@16
|
1206 iter_t i = m.trees.begin();
|
Chris@16
|
1207
|
Chris@16
|
1208 typedef typename value_t::parse_node_t::iterator_t iterator_type;
|
Chris@16
|
1209 iterator_type it = (*i).value.begin();
|
Chris@16
|
1210
|
Chris@16
|
1211 new_children.push_back(
|
Chris@16
|
1212 value_t(typename value_t::parse_node_t(it, it)));
|
Chris@16
|
1213 }
|
Chris@16
|
1214
|
Chris@16
|
1215 m = MatchT(length, new_children);
|
Chris@16
|
1216 }
|
Chris@16
|
1217 };
|
Chris@16
|
1218
|
Chris@16
|
1219 const node_parser_gen<discard_last_node_op> discard_last_node_d =
|
Chris@16
|
1220 node_parser_gen<discard_last_node_op>();
|
Chris@16
|
1221
|
Chris@16
|
1222 struct inner_node_op
|
Chris@16
|
1223 {
|
Chris@16
|
1224 template <typename MatchT>
|
Chris@16
|
1225 void operator()(MatchT& m) const
|
Chris@16
|
1226 {
|
Chris@16
|
1227 typedef typename MatchT::container_t container_t;
|
Chris@16
|
1228 typedef typename MatchT::container_t::iterator iter_t;
|
Chris@16
|
1229 typedef typename MatchT::container_t::value_type value_t;
|
Chris@16
|
1230
|
Chris@16
|
1231 using std::swap;
|
Chris@16
|
1232 using boost::swap;
|
Chris@16
|
1233 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1234
|
Chris@16
|
1235 // copying the tree nodes is expensive, since it may copy a whole
|
Chris@16
|
1236 // tree. swapping them is cheap, so swap the nodes we want into
|
Chris@16
|
1237 // a new container of children, instead of saying
|
Chris@16
|
1238 // m.trees.erase(m.trees.begin()) because, on a container_t that will
|
Chris@16
|
1239 // cause all the nodes afterwards to be copied into the previous
|
Chris@16
|
1240 // position.
|
Chris@16
|
1241 container_t new_children;
|
Chris@16
|
1242 std::size_t length = 0;
|
Chris@16
|
1243 std::size_t tree_size = m.trees.size();
|
Chris@16
|
1244
|
Chris@16
|
1245 // the inner_node_d[] make no sense for nodes with less then 2 subnodes
|
Chris@16
|
1246 BOOST_SPIRIT_ASSERT(tree_size >= 2);
|
Chris@16
|
1247
|
Chris@16
|
1248 if (tree_size > 2) {
|
Chris@16
|
1249 m.trees.pop_back(); // erase the last element
|
Chris@16
|
1250 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
1251 new_children.reserve(tree_size - 1);
|
Chris@16
|
1252 #endif
|
Chris@16
|
1253 iter_t i = m.trees.begin(); // skip over the first element
|
Chris@16
|
1254 iter_t i_end = m.trees.end();
|
Chris@16
|
1255 for (++i; i != i_end; ++i)
|
Chris@16
|
1256 {
|
Chris@16
|
1257 // adjust the length
|
Chris@16
|
1258 length += std::distance((*i).value.begin(), (*i).value.end());
|
Chris@16
|
1259
|
Chris@16
|
1260 // move the child node
|
Chris@16
|
1261 new_children.push_back(value_t());
|
Chris@16
|
1262 swap(new_children.back(), *i);
|
Chris@16
|
1263 }
|
Chris@16
|
1264 }
|
Chris@16
|
1265 else {
|
Chris@16
|
1266 // if there was a tree and now there isn't any, insert an empty node
|
Chris@16
|
1267 iter_t i = m.trees.begin(); // skip over the first element
|
Chris@16
|
1268
|
Chris@16
|
1269 typedef typename value_t::parse_node_t::iterator_t iterator_type;
|
Chris@16
|
1270 iterator_type it = (*++i).value.begin();
|
Chris@16
|
1271
|
Chris@16
|
1272 new_children.push_back(
|
Chris@16
|
1273 value_t(typename value_t::parse_node_t(it, it)));
|
Chris@16
|
1274 }
|
Chris@16
|
1275
|
Chris@16
|
1276 m = MatchT(length, new_children);
|
Chris@16
|
1277 }
|
Chris@16
|
1278 };
|
Chris@16
|
1279
|
Chris@16
|
1280 const node_parser_gen<inner_node_op> inner_node_d =
|
Chris@16
|
1281 node_parser_gen<inner_node_op>();
|
Chris@16
|
1282
|
Chris@16
|
1283
|
Chris@16
|
1284 //////////////////////////////////
|
Chris@16
|
1285 // action_directive_parser and action_directive_parser_gen
|
Chris@16
|
1286 // are meant to be used as a template to create directives that
|
Chris@16
|
1287 // generate action classes. For example access_match and
|
Chris@16
|
1288 // access_node. The ActionParserT template parameter must be
|
Chris@16
|
1289 // a class that has an innter class called action that is templated
|
Chris@16
|
1290 // on the parser type and the action type.
|
Chris@16
|
1291 template <typename ActionParserT>
|
Chris@16
|
1292 struct action_directive_parser_gen;
|
Chris@16
|
1293
|
Chris@16
|
1294 template <typename T, typename ActionParserT>
|
Chris@16
|
1295 struct action_directive_parser
|
Chris@16
|
1296 : public unary<T, parser<action_directive_parser<T, ActionParserT> > >
|
Chris@16
|
1297 {
|
Chris@16
|
1298 typedef action_directive_parser<T, ActionParserT> self_t;
|
Chris@16
|
1299 typedef action_directive_parser_gen<ActionParserT> parser_generator_t;
|
Chris@16
|
1300 typedef unary_parser_category parser_category_t;
|
Chris@16
|
1301
|
Chris@16
|
1302 action_directive_parser(T const& a)
|
Chris@16
|
1303 : unary<T, parser<action_directive_parser<T, ActionParserT> > >(a) {}
|
Chris@16
|
1304
|
Chris@16
|
1305 template <typename ScannerT>
|
Chris@16
|
1306 struct result
|
Chris@16
|
1307 {
|
Chris@16
|
1308 typedef typename parser_result<T, ScannerT>::type type;
|
Chris@16
|
1309 };
|
Chris@16
|
1310
|
Chris@16
|
1311 template <typename ScannerT>
|
Chris@16
|
1312 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
1313 parse(ScannerT const& scanner) const
|
Chris@16
|
1314 {
|
Chris@16
|
1315 return this->subject().parse(scanner);
|
Chris@16
|
1316 }
|
Chris@16
|
1317
|
Chris@16
|
1318 template <typename ActionT>
|
Chris@16
|
1319 typename ActionParserT::template action<action_directive_parser<T, ActionParserT>, ActionT>
|
Chris@16
|
1320 operator[](ActionT const& actor) const
|
Chris@16
|
1321 {
|
Chris@16
|
1322 typedef typename
|
Chris@16
|
1323 ActionParserT::template action<action_directive_parser, ActionT>
|
Chris@16
|
1324 action_t;
|
Chris@16
|
1325 return action_t(*this, actor);
|
Chris@16
|
1326 }
|
Chris@16
|
1327 };
|
Chris@16
|
1328
|
Chris@16
|
1329 //////////////////////////////////
|
Chris@16
|
1330 template <typename ActionParserT>
|
Chris@16
|
1331 struct action_directive_parser_gen
|
Chris@16
|
1332 {
|
Chris@16
|
1333 template <typename T>
|
Chris@16
|
1334 struct result {
|
Chris@16
|
1335
|
Chris@16
|
1336 typedef action_directive_parser<T, ActionParserT> type;
|
Chris@16
|
1337 };
|
Chris@16
|
1338
|
Chris@16
|
1339 template <typename T>
|
Chris@16
|
1340 static action_directive_parser<T, ActionParserT>
|
Chris@16
|
1341 generate(parser<T> const& s)
|
Chris@16
|
1342 {
|
Chris@16
|
1343 return action_directive_parser<T, ActionParserT>(s.derived());
|
Chris@16
|
1344 }
|
Chris@16
|
1345
|
Chris@16
|
1346 template <typename T>
|
Chris@16
|
1347 action_directive_parser<T, ActionParserT>
|
Chris@16
|
1348 operator[](parser<T> const& s) const
|
Chris@16
|
1349 {
|
Chris@16
|
1350 return action_directive_parser<T, ActionParserT>(s.derived());
|
Chris@16
|
1351 }
|
Chris@16
|
1352 };
|
Chris@16
|
1353
|
Chris@16
|
1354 //////////////////////////////////
|
Chris@16
|
1355 // Calls the attached action passing it the match from the parser
|
Chris@16
|
1356 // and the first and last iterators.
|
Chris@16
|
1357 // The inner template class is used to simulate template-template parameters
|
Chris@16
|
1358 // (declared in common_fwd.hpp).
|
Chris@16
|
1359 template <typename ParserT, typename ActionT>
|
Chris@16
|
1360 struct access_match_action::action
|
Chris@16
|
1361 : public unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >
|
Chris@16
|
1362 {
|
Chris@16
|
1363 typedef action_parser_category parser_category;
|
Chris@16
|
1364 typedef action<ParserT, ActionT> self_t;
|
Chris@16
|
1365
|
Chris@16
|
1366 template <typename ScannerT>
|
Chris@16
|
1367 struct result
|
Chris@16
|
1368 {
|
Chris@16
|
1369 typedef typename parser_result<ParserT, ScannerT>::type type;
|
Chris@16
|
1370 };
|
Chris@16
|
1371
|
Chris@16
|
1372 action( ParserT const& subject,
|
Chris@16
|
1373 ActionT const& actor_);
|
Chris@16
|
1374
|
Chris@16
|
1375 template <typename ScannerT>
|
Chris@16
|
1376 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
1377 parse(ScannerT const& scanner) const;
|
Chris@16
|
1378
|
Chris@16
|
1379 ActionT const &predicate() const;
|
Chris@16
|
1380
|
Chris@16
|
1381 private:
|
Chris@16
|
1382 ActionT actor;
|
Chris@16
|
1383 };
|
Chris@16
|
1384
|
Chris@16
|
1385 //////////////////////////////////
|
Chris@16
|
1386 template <typename ParserT, typename ActionT>
|
Chris@16
|
1387 access_match_action::action<ParserT, ActionT>::action(
|
Chris@16
|
1388 ParserT const& subject,
|
Chris@16
|
1389 ActionT const& actor_)
|
Chris@16
|
1390 : unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >(subject)
|
Chris@16
|
1391 , actor(actor_)
|
Chris@16
|
1392 {}
|
Chris@16
|
1393
|
Chris@16
|
1394 //////////////////////////////////
|
Chris@16
|
1395 template <typename ParserT, typename ActionT>
|
Chris@16
|
1396 template <typename ScannerT>
|
Chris@16
|
1397 typename parser_result<access_match_action::action<ParserT, ActionT>, ScannerT>::type
|
Chris@16
|
1398 access_match_action::action<ParserT, ActionT>::
|
Chris@16
|
1399 parse(ScannerT const& scan) const
|
Chris@16
|
1400 {
|
Chris@16
|
1401 typedef typename ScannerT::iterator_t iterator_t;
|
Chris@16
|
1402 typedef typename parser_result<self_t, ScannerT>::type result_t;
|
Chris@16
|
1403 if (!scan.at_end())
|
Chris@16
|
1404 {
|
Chris@16
|
1405 iterator_t save = scan.first;
|
Chris@16
|
1406 result_t hit = this->subject().parse(scan);
|
Chris@16
|
1407 actor(hit, save, scan.first);
|
Chris@16
|
1408 return hit;
|
Chris@16
|
1409 }
|
Chris@16
|
1410 return scan.no_match();
|
Chris@16
|
1411 }
|
Chris@16
|
1412
|
Chris@16
|
1413 //////////////////////////////////
|
Chris@16
|
1414 template <typename ParserT, typename ActionT>
|
Chris@16
|
1415 ActionT const &access_match_action::action<ParserT, ActionT>::predicate() const
|
Chris@16
|
1416 {
|
Chris@16
|
1417 return actor;
|
Chris@16
|
1418 }
|
Chris@16
|
1419
|
Chris@16
|
1420 //////////////////////////////////
|
Chris@16
|
1421 const action_directive_parser_gen<access_match_action> access_match_d
|
Chris@16
|
1422 = action_directive_parser_gen<access_match_action>();
|
Chris@16
|
1423
|
Chris@16
|
1424
|
Chris@16
|
1425
|
Chris@16
|
1426 //////////////////////////////////
|
Chris@16
|
1427 // Calls the attached action passing it the node from the parser
|
Chris@16
|
1428 // and the first and last iterators
|
Chris@16
|
1429 // The inner template class is used to simulate template-template parameters
|
Chris@16
|
1430 // (declared in common_fwd.hpp).
|
Chris@16
|
1431 template <typename ParserT, typename ActionT>
|
Chris@16
|
1432 struct access_node_action::action
|
Chris@16
|
1433 : public unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >
|
Chris@16
|
1434 {
|
Chris@16
|
1435 typedef action_parser_category parser_category;
|
Chris@16
|
1436 typedef action<ParserT, ActionT> self_t;
|
Chris@16
|
1437
|
Chris@16
|
1438 template <typename ScannerT>
|
Chris@16
|
1439 struct result
|
Chris@16
|
1440 {
|
Chris@16
|
1441 typedef typename parser_result<ParserT, ScannerT>::type type;
|
Chris@16
|
1442 };
|
Chris@16
|
1443
|
Chris@16
|
1444 action( ParserT const& subject,
|
Chris@16
|
1445 ActionT const& actor_);
|
Chris@16
|
1446
|
Chris@16
|
1447 template <typename ScannerT>
|
Chris@16
|
1448 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
1449 parse(ScannerT const& scanner) const;
|
Chris@16
|
1450
|
Chris@16
|
1451 ActionT const &predicate() const;
|
Chris@16
|
1452
|
Chris@16
|
1453 private:
|
Chris@16
|
1454 ActionT actor;
|
Chris@16
|
1455 };
|
Chris@16
|
1456
|
Chris@16
|
1457 //////////////////////////////////
|
Chris@16
|
1458 template <typename ParserT, typename ActionT>
|
Chris@16
|
1459 access_node_action::action<ParserT, ActionT>::action(
|
Chris@16
|
1460 ParserT const& subject,
|
Chris@16
|
1461 ActionT const& actor_)
|
Chris@16
|
1462 : unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >(subject)
|
Chris@16
|
1463 , actor(actor_)
|
Chris@16
|
1464 {}
|
Chris@16
|
1465
|
Chris@16
|
1466 //////////////////////////////////
|
Chris@16
|
1467 template <typename ParserT, typename ActionT>
|
Chris@16
|
1468 template <typename ScannerT>
|
Chris@16
|
1469 typename parser_result<access_node_action::action<ParserT, ActionT>, ScannerT>::type
|
Chris@16
|
1470 access_node_action::action<ParserT, ActionT>::
|
Chris@16
|
1471 parse(ScannerT const& scan) const
|
Chris@16
|
1472 {
|
Chris@16
|
1473 typedef typename ScannerT::iterator_t iterator_t;
|
Chris@16
|
1474 typedef typename parser_result<self_t, ScannerT>::type result_t;
|
Chris@16
|
1475 if (!scan.at_end())
|
Chris@16
|
1476 {
|
Chris@16
|
1477 iterator_t save = scan.first;
|
Chris@16
|
1478 result_t hit = this->subject().parse(scan);
|
Chris@16
|
1479 if (hit && hit.trees.size() > 0)
|
Chris@16
|
1480 actor(*hit.trees.begin(), save, scan.first);
|
Chris@16
|
1481 return hit;
|
Chris@16
|
1482 }
|
Chris@16
|
1483 return scan.no_match();
|
Chris@16
|
1484 }
|
Chris@16
|
1485
|
Chris@16
|
1486 //////////////////////////////////
|
Chris@16
|
1487 template <typename ParserT, typename ActionT>
|
Chris@16
|
1488 ActionT const &access_node_action::action<ParserT, ActionT>::predicate() const
|
Chris@16
|
1489 {
|
Chris@16
|
1490 return actor;
|
Chris@16
|
1491 }
|
Chris@16
|
1492
|
Chris@16
|
1493 //////////////////////////////////
|
Chris@16
|
1494 const action_directive_parser_gen<access_node_action> access_node_d
|
Chris@16
|
1495 = action_directive_parser_gen<access_node_action>();
|
Chris@16
|
1496
|
Chris@16
|
1497
|
Chris@16
|
1498
|
Chris@16
|
1499 //////////////////////////////////
|
Chris@16
|
1500
|
Chris@16
|
1501 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1502 //
|
Chris@16
|
1503 // tree_parse_info
|
Chris@16
|
1504 //
|
Chris@16
|
1505 // Results returned by the tree parse functions:
|
Chris@16
|
1506 //
|
Chris@16
|
1507 // stop: points to the final parse position (i.e parsing
|
Chris@16
|
1508 // processed the input up to this point).
|
Chris@16
|
1509 //
|
Chris@16
|
1510 // match: true if parsing is successful. This may be full:
|
Chris@16
|
1511 // the parser consumed all the input, or partial:
|
Chris@16
|
1512 // the parser consumed only a portion of the input.
|
Chris@16
|
1513 //
|
Chris@16
|
1514 // full: true when we have a full match (i.e the parser
|
Chris@16
|
1515 // consumed all the input.
|
Chris@16
|
1516 //
|
Chris@16
|
1517 // length: The number of characters consumed by the parser.
|
Chris@16
|
1518 // This is valid only if we have a successful match
|
Chris@16
|
1519 // (either partial or full). A negative value means
|
Chris@16
|
1520 // that the match is unsucessful.
|
Chris@16
|
1521 //
|
Chris@16
|
1522 // trees: Contains the root node(s) of the tree.
|
Chris@16
|
1523 //
|
Chris@16
|
1524 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1525 template <
|
Chris@16
|
1526 typename IteratorT,
|
Chris@16
|
1527 typename NodeFactoryT,
|
Chris@16
|
1528 typename T
|
Chris@16
|
1529 >
|
Chris@16
|
1530 struct tree_parse_info
|
Chris@16
|
1531 {
|
Chris@16
|
1532 IteratorT stop;
|
Chris@16
|
1533 bool match;
|
Chris@16
|
1534 bool full;
|
Chris@16
|
1535 std::size_t length;
|
Chris@16
|
1536 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees;
|
Chris@16
|
1537
|
Chris@16
|
1538 tree_parse_info()
|
Chris@16
|
1539 : stop()
|
Chris@16
|
1540 , match(false)
|
Chris@16
|
1541 , full(false)
|
Chris@16
|
1542 , length(0)
|
Chris@16
|
1543 , trees()
|
Chris@16
|
1544 {}
|
Chris@16
|
1545
|
Chris@16
|
1546 template <typename IteratorT2>
|
Chris@16
|
1547 tree_parse_info(tree_parse_info<IteratorT2> const& pi)
|
Chris@16
|
1548 : stop(pi.stop)
|
Chris@16
|
1549 , match(pi.match)
|
Chris@16
|
1550 , full(pi.full)
|
Chris@16
|
1551 , length(pi.length)
|
Chris@16
|
1552 , trees()
|
Chris@16
|
1553 {
|
Chris@16
|
1554 using std::swap;
|
Chris@16
|
1555 using boost::swap;
|
Chris@16
|
1556 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1557
|
Chris@16
|
1558 // use auto_ptr like ownership for the trees data member
|
Chris@16
|
1559 swap(trees, pi.trees);
|
Chris@16
|
1560 }
|
Chris@16
|
1561
|
Chris@16
|
1562 tree_parse_info(
|
Chris@16
|
1563 IteratorT stop_,
|
Chris@16
|
1564 bool match_,
|
Chris@16
|
1565 bool full_,
|
Chris@16
|
1566 std::size_t length_,
|
Chris@16
|
1567 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees_)
|
Chris@16
|
1568 : stop(stop_)
|
Chris@16
|
1569 , match(match_)
|
Chris@16
|
1570 , full(full_)
|
Chris@16
|
1571 , length(length_)
|
Chris@16
|
1572 , trees()
|
Chris@16
|
1573 {
|
Chris@16
|
1574 using std::swap;
|
Chris@16
|
1575 using boost::swap;
|
Chris@16
|
1576 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1577
|
Chris@16
|
1578 // use auto_ptr like ownership for the trees data member
|
Chris@16
|
1579 swap(trees, trees_);
|
Chris@16
|
1580 }
|
Chris@16
|
1581 };
|
Chris@16
|
1582
|
Chris@16
|
1583 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
|
Chris@16
|
1584
|
Chris@16
|
1585 }} // namespace BOOST_SPIRIT_CLASSIC_NS
|
Chris@16
|
1586
|
Chris@16
|
1587 #endif
|
Chris@16
|
1588
|