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 template <typename T>
|
Chris@16
|
524 inline void cp_swap(T& t1, T& t2)
|
Chris@16
|
525 {
|
Chris@16
|
526 using std::swap;
|
Chris@16
|
527 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
528 using boost::swap;
|
Chris@16
|
529 swap(t1, t2);
|
Chris@16
|
530 }
|
Chris@16
|
531 }
|
Chris@16
|
532
|
Chris@16
|
533 //////////////////////////////////
|
Chris@16
|
534 template <typename IteratorT, typename NodeFactoryT, typename T>
|
Chris@16
|
535 class tree_match : public match<T>
|
Chris@16
|
536 {
|
Chris@16
|
537 public:
|
Chris@16
|
538
|
Chris@16
|
539 typedef typename NodeFactoryT::template factory<IteratorT> node_factory_t;
|
Chris@16
|
540 typedef typename node_factory_t::node_t parse_node_t;
|
Chris@16
|
541 typedef tree_node<parse_node_t> node_t;
|
Chris@16
|
542 typedef typename node_t::children_t container_t;
|
Chris@16
|
543 typedef typename container_t::iterator tree_iterator;
|
Chris@16
|
544 typedef typename container_t::const_iterator const_tree_iterator;
|
Chris@16
|
545
|
Chris@16
|
546 typedef T attr_t;
|
Chris@16
|
547 typedef typename boost::call_traits<T>::param_type param_type;
|
Chris@16
|
548 typedef typename boost::call_traits<T>::reference reference;
|
Chris@16
|
549 typedef typename boost::call_traits<T>::const_reference const_reference;
|
Chris@16
|
550
|
Chris@16
|
551 tree_match()
|
Chris@16
|
552 : match<T>(), trees()
|
Chris@16
|
553 {}
|
Chris@16
|
554
|
Chris@16
|
555 explicit
|
Chris@16
|
556 tree_match(std::size_t length_)
|
Chris@16
|
557 : match<T>(length_), trees()
|
Chris@16
|
558 {}
|
Chris@16
|
559
|
Chris@16
|
560 tree_match(std::size_t length_, parse_node_t const& n)
|
Chris@16
|
561 : match<T>(length_), trees()
|
Chris@16
|
562 {
|
Chris@16
|
563 trees.push_back(node_t(n));
|
Chris@16
|
564 }
|
Chris@16
|
565
|
Chris@16
|
566 tree_match(std::size_t length_, param_type val, parse_node_t const& n)
|
Chris@16
|
567 : match<T>(length_, val), trees()
|
Chris@16
|
568 {
|
Chris@16
|
569 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
570 trees.reserve(10); // this is more or less an arbitrary number...
|
Chris@16
|
571 #endif
|
Chris@16
|
572 trees.push_back(node_t(n));
|
Chris@16
|
573 }
|
Chris@16
|
574
|
Chris@16
|
575 // attention, these constructors will change the second parameter!
|
Chris@16
|
576 tree_match(std::size_t length_, container_t& c)
|
Chris@16
|
577 : match<T>(length_), trees()
|
Chris@16
|
578 {
|
Chris@16
|
579 impl::cp_swap(trees, c);
|
Chris@16
|
580 }
|
Chris@16
|
581
|
Chris@16
|
582 tree_match(std::size_t length_, param_type val, container_t& c)
|
Chris@16
|
583 : match<T>(length_, val), trees()
|
Chris@16
|
584 {
|
Chris@16
|
585 impl::cp_swap(trees, c);
|
Chris@16
|
586 }
|
Chris@16
|
587
|
Chris@16
|
588 template <typename T2>
|
Chris@16
|
589 tree_match(match<T2> const& other)
|
Chris@16
|
590 : match<T>(other), trees()
|
Chris@16
|
591 {}
|
Chris@16
|
592
|
Chris@16
|
593 template <typename T2, typename T3, typename T4>
|
Chris@16
|
594 tree_match(tree_match<T2, T3, T4> const& other)
|
Chris@16
|
595 : match<T>(other), trees()
|
Chris@16
|
596 { impl::cp_swap(trees, other.trees); }
|
Chris@16
|
597
|
Chris@16
|
598 template <typename T2>
|
Chris@16
|
599 tree_match&
|
Chris@16
|
600 operator=(match<T2> const& other)
|
Chris@16
|
601 {
|
Chris@16
|
602 match<T>::operator=(other);
|
Chris@16
|
603 return *this;
|
Chris@16
|
604 }
|
Chris@16
|
605
|
Chris@16
|
606 template <typename T2, typename T3, typename T4>
|
Chris@16
|
607 tree_match&
|
Chris@16
|
608 operator=(tree_match<T2, T3, T4> const& other)
|
Chris@16
|
609 {
|
Chris@16
|
610 match<T>::operator=(other);
|
Chris@16
|
611 impl::cp_swap(trees, other.trees);
|
Chris@16
|
612 return *this;
|
Chris@16
|
613 }
|
Chris@16
|
614
|
Chris@16
|
615 tree_match(tree_match const& x)
|
Chris@16
|
616 : match<T>(x), trees()
|
Chris@16
|
617 {
|
Chris@16
|
618 // use auto_ptr like ownership for the trees data member
|
Chris@16
|
619 impl::cp_swap(trees, x.trees);
|
Chris@16
|
620 }
|
Chris@16
|
621
|
Chris@16
|
622 tree_match& operator=(tree_match const& x)
|
Chris@16
|
623 {
|
Chris@16
|
624 tree_match tmp(x);
|
Chris@16
|
625 this->swap(tmp);
|
Chris@16
|
626 return *this;
|
Chris@16
|
627 }
|
Chris@16
|
628
|
Chris@16
|
629 void swap(tree_match& x)
|
Chris@16
|
630 {
|
Chris@16
|
631 match<T>::swap(x);
|
Chris@16
|
632 impl::cp_swap(trees, x.trees);
|
Chris@16
|
633 }
|
Chris@16
|
634
|
Chris@16
|
635 mutable container_t trees;
|
Chris@16
|
636 };
|
Chris@16
|
637
|
Chris@16
|
638 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
639 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
640 template <typename IteratorT, typename NodeFactoryT, typename T>
|
Chris@16
|
641 inline std::ostream&
|
Chris@16
|
642 operator<<(std::ostream& o, tree_match<IteratorT, NodeFactoryT, T> const& m)
|
Chris@16
|
643 {
|
Chris@16
|
644 typedef
|
Chris@16
|
645 typename tree_match<IteratorT, NodeFactoryT, T>::container_t::iterator
|
Chris@16
|
646 iterator;
|
Chris@16
|
647
|
Chris@16
|
648 o << "(length = " << (int)m.length();
|
Chris@16
|
649 int c = 0;
|
Chris@16
|
650 for (iterator i = m.trees.begin(); i != m.trees.end(); ++i)
|
Chris@16
|
651 {
|
Chris@16
|
652 o << " trees[" << c++ << "] = " << *i;
|
Chris@16
|
653 }
|
Chris@16
|
654 o << "\n)";
|
Chris@16
|
655 return o;
|
Chris@16
|
656 }
|
Chris@16
|
657 #endif
|
Chris@16
|
658
|
Chris@16
|
659 //////////////////////////////////
|
Chris@16
|
660 struct tree_policy
|
Chris@16
|
661 {
|
Chris@16
|
662 template <typename FunctorT, typename MatchT>
|
Chris@16
|
663 static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/)
|
Chris@16
|
664 {}
|
Chris@16
|
665
|
Chris@16
|
666 template <typename MatchT, typename Iterator1T, typename Iterator2T>
|
Chris@16
|
667 static void group_match(MatchT& /*m*/, parser_id const& /*id*/,
|
Chris@16
|
668 Iterator1T const& /*first*/, Iterator2T const& /*last*/)
|
Chris@16
|
669 {}
|
Chris@16
|
670
|
Chris@16
|
671 template <typename MatchT>
|
Chris@16
|
672 static void concat(MatchT& /*a*/, MatchT const& /*b*/)
|
Chris@16
|
673 {}
|
Chris@16
|
674 };
|
Chris@16
|
675
|
Chris@16
|
676 //////////////////////////////////
|
Chris@16
|
677 template <
|
Chris@16
|
678 typename MatchPolicyT,
|
Chris@16
|
679 typename IteratorT,
|
Chris@16
|
680 typename NodeFactoryT,
|
Chris@16
|
681 typename TreePolicyT,
|
Chris@16
|
682 typename T
|
Chris@16
|
683 >
|
Chris@16
|
684 struct common_tree_match_policy : public match_policy
|
Chris@16
|
685 {
|
Chris@16
|
686 common_tree_match_policy()
|
Chris@16
|
687 {
|
Chris@16
|
688 }
|
Chris@16
|
689
|
Chris@16
|
690 template <typename PolicyT>
|
Chris@16
|
691 common_tree_match_policy(PolicyT const & policies)
|
Chris@16
|
692 : match_policy((match_policy const &)policies)
|
Chris@16
|
693 {
|
Chris@16
|
694 }
|
Chris@16
|
695
|
Chris@16
|
696 template <typename U>
|
Chris@16
|
697 struct result { typedef tree_match<IteratorT, NodeFactoryT, U> type; };
|
Chris@16
|
698
|
Chris@16
|
699 typedef tree_match<IteratorT, NodeFactoryT, T> match_t;
|
Chris@16
|
700 typedef IteratorT iterator_t;
|
Chris@16
|
701 typedef TreePolicyT tree_policy_t;
|
Chris@16
|
702 typedef NodeFactoryT factory_t;
|
Chris@16
|
703
|
Chris@16
|
704 static const match_t no_match() { return match_t(); }
|
Chris@16
|
705 static const match_t empty_match()
|
Chris@16
|
706 { return match_t(0, tree_policy_t::empty_node()); }
|
Chris@16
|
707
|
Chris@16
|
708 template <typename AttrT, typename Iterator1T, typename Iterator2T>
|
Chris@16
|
709 static tree_match<IteratorT, NodeFactoryT, AttrT> create_match(
|
Chris@16
|
710 std::size_t length,
|
Chris@16
|
711 AttrT const& val,
|
Chris@16
|
712 Iterator1T const& first,
|
Chris@16
|
713 Iterator2T const& last)
|
Chris@16
|
714 {
|
Chris@16
|
715 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
716 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
717
|
Chris@16
|
718 BOOST_SPIRIT_DEBUG_OUT << "\n>>> create_node(begin) <<<\n"
|
Chris@16
|
719 "creating node text: \"";
|
Chris@16
|
720 for (Iterator1T it = first; it != last; ++it)
|
Chris@16
|
721 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
|
Chris@16
|
722 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
|
Chris@16
|
723 BOOST_SPIRIT_DEBUG_OUT << ">>> create_node(end) <<<\n\n";
|
Chris@16
|
724 #endif
|
Chris@16
|
725 return tree_match<IteratorT, NodeFactoryT, AttrT>(length, val,
|
Chris@16
|
726 tree_policy_t::create_node(length, first, last, true));
|
Chris@16
|
727 }
|
Chris@16
|
728
|
Chris@16
|
729 template <typename Match1T, typename Match2T>
|
Chris@16
|
730 static void concat_match(Match1T& a, Match2T const& b)
|
Chris@16
|
731 {
|
Chris@16
|
732 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
733 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
|
Chris@16
|
734
|
Chris@16
|
735 BOOST_SPIRIT_DEBUG_OUT << "\n>>> concat_match(begin) <<<\n";
|
Chris@16
|
736 BOOST_SPIRIT_DEBUG_OUT << "tree a:\n" << a << "\n";
|
Chris@16
|
737 BOOST_SPIRIT_DEBUG_OUT << "tree b:\n" << b << "\n";
|
Chris@16
|
738 BOOST_SPIRIT_DEBUG_OUT << ">>> concat_match(end) <<<\n\n";
|
Chris@16
|
739 #endif
|
Chris@16
|
740 BOOST_SPIRIT_ASSERT(a && b);
|
Chris@16
|
741 if (a.length() == 0)
|
Chris@16
|
742 {
|
Chris@16
|
743 a = b;
|
Chris@16
|
744 return;
|
Chris@16
|
745 }
|
Chris@16
|
746 else if (b.length() == 0
|
Chris@16
|
747 #ifdef BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING
|
Chris@16
|
748 && !b.trees.begin()->value.id().to_long()
|
Chris@16
|
749 #endif
|
Chris@16
|
750 )
|
Chris@16
|
751 {
|
Chris@16
|
752 return;
|
Chris@16
|
753 }
|
Chris@16
|
754 a.concat(b);
|
Chris@16
|
755 tree_policy_t::concat(a, b);
|
Chris@16
|
756 }
|
Chris@16
|
757
|
Chris@16
|
758 template <typename MatchT, typename IteratorT2>
|
Chris@16
|
759 void
|
Chris@16
|
760 group_match(
|
Chris@16
|
761 MatchT& m,
|
Chris@16
|
762 parser_id const& id,
|
Chris@16
|
763 IteratorT2 const& first,
|
Chris@16
|
764 IteratorT2 const& last) const
|
Chris@16
|
765 {
|
Chris@16
|
766 if (!m) return;
|
Chris@16
|
767
|
Chris@16
|
768 #if defined(BOOST_SPIRIT_DEBUG) && \
|
Chris@16
|
769 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_TREES)
|
Chris@16
|
770
|
Chris@16
|
771 BOOST_SPIRIT_DEBUG_OUT << "\n>>> group_match(begin) <<<\n"
|
Chris@16
|
772 "new node(" << id << ") \"";
|
Chris@16
|
773 for (IteratorT2 it = first; it != last; ++it)
|
Chris@16
|
774 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
|
Chris@16
|
775 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
|
Chris@16
|
776 BOOST_SPIRIT_DEBUG_OUT << "new child tree (before grouping):\n" << m << "\n";
|
Chris@16
|
777
|
Chris@16
|
778 tree_policy_t::group_match(m, id, first, last);
|
Chris@16
|
779
|
Chris@16
|
780 BOOST_SPIRIT_DEBUG_OUT << "new child tree (after grouping):\n" << m << "\n";
|
Chris@16
|
781 BOOST_SPIRIT_DEBUG_OUT << ">>> group_match(end) <<<\n\n";
|
Chris@16
|
782 #else
|
Chris@16
|
783 tree_policy_t::group_match(m, id, first, last);
|
Chris@16
|
784 #endif
|
Chris@16
|
785 }
|
Chris@16
|
786 };
|
Chris@16
|
787
|
Chris@16
|
788 //////////////////////////////////
|
Chris@16
|
789 template <typename MatchPolicyT, typename NodeFactoryT>
|
Chris@16
|
790 struct common_tree_tree_policy
|
Chris@16
|
791 {
|
Chris@16
|
792 typedef typename MatchPolicyT::iterator_t iterator_t;
|
Chris@16
|
793 typedef typename MatchPolicyT::match_t match_t;
|
Chris@16
|
794 typedef typename NodeFactoryT::template factory<iterator_t> factory_t;
|
Chris@16
|
795 typedef typename factory_t::node_t node_t;
|
Chris@16
|
796
|
Chris@16
|
797 template <typename Iterator1T, typename Iterator2T>
|
Chris@16
|
798 static node_t
|
Chris@16
|
799 create_node(std::size_t /*length*/, Iterator1T const& first,
|
Chris@16
|
800 Iterator2T const& last, bool leaf_node)
|
Chris@16
|
801 {
|
Chris@16
|
802 return factory_t::create_node(first, last, leaf_node);
|
Chris@16
|
803 }
|
Chris@16
|
804
|
Chris@16
|
805 static node_t
|
Chris@16
|
806 empty_node()
|
Chris@16
|
807 {
|
Chris@16
|
808 return factory_t::empty_node();
|
Chris@16
|
809 }
|
Chris@16
|
810
|
Chris@16
|
811 template <typename FunctorT>
|
Chris@16
|
812 static void apply_op_to_match(FunctorT const& op, match_t& m)
|
Chris@16
|
813 {
|
Chris@16
|
814 op(m);
|
Chris@16
|
815 }
|
Chris@16
|
816 };
|
Chris@16
|
817
|
Chris@16
|
818 //////////////////////////////////
|
Chris@16
|
819 // directives to modify how the parse tree is generated
|
Chris@16
|
820
|
Chris@16
|
821 struct no_tree_gen_node_parser_gen;
|
Chris@16
|
822
|
Chris@16
|
823 template <typename T>
|
Chris@16
|
824 struct no_tree_gen_node_parser
|
Chris@16
|
825 : public unary<T, parser<no_tree_gen_node_parser<T> > >
|
Chris@16
|
826 {
|
Chris@16
|
827 typedef no_tree_gen_node_parser<T> self_t;
|
Chris@16
|
828 typedef no_tree_gen_node_parser_gen parser_generator_t;
|
Chris@16
|
829 typedef unary_parser_category parser_category_t;
|
Chris@16
|
830
|
Chris@16
|
831 no_tree_gen_node_parser(T const& a)
|
Chris@16
|
832 : unary<T, parser<no_tree_gen_node_parser<T> > >(a) {}
|
Chris@16
|
833
|
Chris@16
|
834 template <typename ScannerT>
|
Chris@16
|
835 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
836 parse(ScannerT const& scanner) const
|
Chris@16
|
837 {
|
Chris@16
|
838 typedef typename ScannerT::iteration_policy_t iteration_policy_t;
|
Chris@16
|
839 typedef match_policy match_policy_t;
|
Chris@16
|
840 typedef typename ScannerT::action_policy_t action_policy_t;
|
Chris@16
|
841 typedef scanner_policies<
|
Chris@16
|
842 iteration_policy_t,
|
Chris@16
|
843 match_policy_t,
|
Chris@16
|
844 action_policy_t
|
Chris@16
|
845 > policies_t;
|
Chris@16
|
846
|
Chris@16
|
847 return this->subject().parse(scanner.change_policies(policies_t(scanner)));
|
Chris@16
|
848 }
|
Chris@16
|
849 };
|
Chris@16
|
850
|
Chris@16
|
851 struct no_tree_gen_node_parser_gen
|
Chris@16
|
852 {
|
Chris@16
|
853 template <typename T>
|
Chris@16
|
854 struct result {
|
Chris@16
|
855
|
Chris@16
|
856 typedef no_tree_gen_node_parser<T> type;
|
Chris@16
|
857 };
|
Chris@16
|
858
|
Chris@16
|
859 template <typename T>
|
Chris@16
|
860 static no_tree_gen_node_parser<T>
|
Chris@16
|
861 generate(parser<T> const& s)
|
Chris@16
|
862 {
|
Chris@16
|
863 return no_tree_gen_node_parser<T>(s.derived());
|
Chris@16
|
864 }
|
Chris@16
|
865
|
Chris@16
|
866 template <typename T>
|
Chris@16
|
867 no_tree_gen_node_parser<T>
|
Chris@16
|
868 operator[](parser<T> const& s) const
|
Chris@16
|
869 {
|
Chris@16
|
870 return no_tree_gen_node_parser<T>(s.derived());
|
Chris@16
|
871 }
|
Chris@16
|
872 };
|
Chris@16
|
873
|
Chris@16
|
874 const no_tree_gen_node_parser_gen no_node_d = no_tree_gen_node_parser_gen();
|
Chris@16
|
875
|
Chris@16
|
876 //////////////////////////////////
|
Chris@16
|
877
|
Chris@16
|
878 struct leaf_node_parser_gen;
|
Chris@16
|
879
|
Chris@16
|
880 template<typename T>
|
Chris@16
|
881 struct leaf_node_parser
|
Chris@16
|
882 : public unary<T, parser<leaf_node_parser<T> > >
|
Chris@16
|
883 {
|
Chris@16
|
884 typedef leaf_node_parser<T> self_t;
|
Chris@16
|
885 typedef leaf_node_parser_gen parser_generator_t;
|
Chris@16
|
886 typedef unary_parser_category parser_category_t;
|
Chris@16
|
887
|
Chris@16
|
888 leaf_node_parser(T const& a)
|
Chris@16
|
889 : unary<T, parser<leaf_node_parser<T> > >(a) {}
|
Chris@16
|
890
|
Chris@16
|
891 template <typename ScannerT>
|
Chris@16
|
892 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
893 parse(ScannerT const& scanner) const
|
Chris@16
|
894 {
|
Chris@16
|
895 typedef scanner_policies< typename ScannerT::iteration_policy_t,
|
Chris@16
|
896 match_policy, typename ScannerT::action_policy_t > policies_t;
|
Chris@16
|
897
|
Chris@16
|
898 typedef typename ScannerT::iterator_t iterator_t;
|
Chris@16
|
899 typedef typename parser_result<self_t, ScannerT>::type result_t;
|
Chris@16
|
900 typedef typename result_t::node_factory_t factory_t;
|
Chris@16
|
901
|
Chris@16
|
902 iterator_t from = scanner.first;
|
Chris@16
|
903 result_t hit = impl::contiguous_parser_parse<result_t>(this->subject(),
|
Chris@16
|
904 scanner.change_policies(policies_t(scanner,match_policy(),scanner)),
|
Chris@16
|
905 scanner);
|
Chris@16
|
906
|
Chris@16
|
907 if (hit)
|
Chris@16
|
908 return result_t(hit.length(),
|
Chris@16
|
909 factory_t::create_node(from, scanner.first, true));
|
Chris@16
|
910 else
|
Chris@16
|
911 return result_t(hit.length());
|
Chris@16
|
912 }
|
Chris@16
|
913 };
|
Chris@16
|
914
|
Chris@16
|
915 struct leaf_node_parser_gen
|
Chris@16
|
916 {
|
Chris@16
|
917 template <typename T>
|
Chris@16
|
918 struct result {
|
Chris@16
|
919
|
Chris@16
|
920 typedef leaf_node_parser<T> type;
|
Chris@16
|
921 };
|
Chris@16
|
922
|
Chris@16
|
923 template <typename T>
|
Chris@16
|
924 static leaf_node_parser<T>
|
Chris@16
|
925 generate(parser<T> const& s)
|
Chris@16
|
926 {
|
Chris@16
|
927 return leaf_node_parser<T>(s.derived());
|
Chris@16
|
928 }
|
Chris@16
|
929
|
Chris@16
|
930 template <typename T>
|
Chris@16
|
931 leaf_node_parser<T>
|
Chris@16
|
932 operator[](parser<T> const& s) const
|
Chris@16
|
933 {
|
Chris@16
|
934 return leaf_node_parser<T>(s.derived());
|
Chris@16
|
935 }
|
Chris@16
|
936 };
|
Chris@16
|
937
|
Chris@16
|
938 const leaf_node_parser_gen leaf_node_d = leaf_node_parser_gen();
|
Chris@16
|
939 const leaf_node_parser_gen token_node_d = leaf_node_parser_gen();
|
Chris@16
|
940
|
Chris@16
|
941 //////////////////////////////////
|
Chris@16
|
942 namespace impl {
|
Chris@16
|
943
|
Chris@16
|
944 template <typename MatchPolicyT>
|
Chris@16
|
945 struct tree_policy_selector
|
Chris@16
|
946 {
|
Chris@16
|
947 typedef tree_policy type;
|
Chris@16
|
948 };
|
Chris@16
|
949
|
Chris@16
|
950 } // namespace impl
|
Chris@16
|
951
|
Chris@16
|
952 //////////////////////////////////
|
Chris@16
|
953 template <typename NodeParserT>
|
Chris@16
|
954 struct node_parser_gen;
|
Chris@16
|
955
|
Chris@16
|
956 template <typename T, typename NodeParserT>
|
Chris@16
|
957 struct node_parser
|
Chris@16
|
958 : public unary<T, parser<node_parser<T, NodeParserT> > >
|
Chris@16
|
959 {
|
Chris@16
|
960 typedef node_parser<T, NodeParserT> self_t;
|
Chris@16
|
961 typedef node_parser_gen<NodeParserT> parser_generator_t;
|
Chris@16
|
962 typedef unary_parser_category parser_category_t;
|
Chris@16
|
963
|
Chris@16
|
964 node_parser(T const& a)
|
Chris@16
|
965 : unary<T, parser<node_parser<T, NodeParserT> > >(a) {}
|
Chris@16
|
966
|
Chris@16
|
967 template <typename ScannerT>
|
Chris@16
|
968 struct result
|
Chris@16
|
969 {
|
Chris@16
|
970 typedef typename parser_result<T, ScannerT>::type type;
|
Chris@16
|
971 };
|
Chris@16
|
972
|
Chris@16
|
973 template <typename ScannerT>
|
Chris@16
|
974 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
975 parse(ScannerT const& scanner) const
|
Chris@16
|
976 {
|
Chris@16
|
977 typename parser_result<self_t, ScannerT>::type hit = this->subject().parse(scanner);
|
Chris@16
|
978 if (hit)
|
Chris@16
|
979 {
|
Chris@16
|
980 impl::tree_policy_selector<typename ScannerT::match_policy_t>::type::apply_op_to_match(NodeParserT(), hit);
|
Chris@16
|
981 }
|
Chris@16
|
982 return hit;
|
Chris@16
|
983 }
|
Chris@16
|
984 };
|
Chris@16
|
985
|
Chris@16
|
986 template <typename NodeParserT>
|
Chris@16
|
987 struct node_parser_gen
|
Chris@16
|
988 {
|
Chris@16
|
989 template <typename T>
|
Chris@16
|
990 struct result {
|
Chris@16
|
991
|
Chris@16
|
992 typedef node_parser<T, NodeParserT> type;
|
Chris@16
|
993 };
|
Chris@16
|
994
|
Chris@16
|
995 template <typename T>
|
Chris@16
|
996 static node_parser<T, NodeParserT>
|
Chris@16
|
997 generate(parser<T> const& s)
|
Chris@16
|
998 {
|
Chris@16
|
999 return node_parser<T, NodeParserT>(s.derived());
|
Chris@16
|
1000 }
|
Chris@16
|
1001
|
Chris@16
|
1002 template <typename T>
|
Chris@16
|
1003 node_parser<T, NodeParserT>
|
Chris@16
|
1004 operator[](parser<T> const& s) const
|
Chris@16
|
1005 {
|
Chris@16
|
1006 return node_parser<T, NodeParserT>(s.derived());
|
Chris@16
|
1007 }
|
Chris@16
|
1008 };
|
Chris@16
|
1009 //////////////////////////////////
|
Chris@16
|
1010 struct reduced_node_op
|
Chris@16
|
1011 {
|
Chris@16
|
1012 template <typename MatchT>
|
Chris@16
|
1013 void operator()(MatchT& m) const
|
Chris@16
|
1014 {
|
Chris@16
|
1015 if (m.trees.size() == 1)
|
Chris@16
|
1016 {
|
Chris@16
|
1017 m.trees.begin()->children.clear();
|
Chris@16
|
1018 }
|
Chris@16
|
1019 else if (m.trees.size() > 1)
|
Chris@16
|
1020 {
|
Chris@16
|
1021 typedef typename MatchT::node_factory_t node_factory_t;
|
Chris@16
|
1022 m = MatchT(m.length(), node_factory_t::group_nodes(m.trees));
|
Chris@16
|
1023 }
|
Chris@16
|
1024 }
|
Chris@16
|
1025 };
|
Chris@16
|
1026
|
Chris@16
|
1027 const node_parser_gen<reduced_node_op> reduced_node_d =
|
Chris@16
|
1028 node_parser_gen<reduced_node_op>();
|
Chris@16
|
1029
|
Chris@16
|
1030
|
Chris@16
|
1031 struct discard_node_op
|
Chris@16
|
1032 {
|
Chris@16
|
1033 template <typename MatchT>
|
Chris@16
|
1034 void operator()(MatchT& m) const
|
Chris@16
|
1035 {
|
Chris@16
|
1036 m.trees.clear();
|
Chris@16
|
1037 }
|
Chris@16
|
1038 };
|
Chris@16
|
1039
|
Chris@16
|
1040 const node_parser_gen<discard_node_op> discard_node_d =
|
Chris@16
|
1041 node_parser_gen<discard_node_op>();
|
Chris@16
|
1042
|
Chris@16
|
1043 struct infix_node_op
|
Chris@16
|
1044 {
|
Chris@16
|
1045 template <typename MatchT>
|
Chris@16
|
1046 void operator()(MatchT& m) const
|
Chris@16
|
1047 {
|
Chris@16
|
1048 typedef typename MatchT::container_t container_t;
|
Chris@16
|
1049 typedef typename MatchT::container_t::iterator iter_t;
|
Chris@16
|
1050 typedef typename MatchT::container_t::value_type value_t;
|
Chris@16
|
1051
|
Chris@16
|
1052 using std::swap;
|
Chris@16
|
1053 using boost::swap;
|
Chris@16
|
1054 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1055
|
Chris@16
|
1056 // copying the tree nodes is expensive, since it may copy a whole
|
Chris@16
|
1057 // tree. swapping them is cheap, so swap the nodes we want into
|
Chris@16
|
1058 // a new container of children.
|
Chris@16
|
1059 container_t new_children;
|
Chris@16
|
1060 std::size_t length = 0;
|
Chris@16
|
1061 std::size_t tree_size = m.trees.size();
|
Chris@16
|
1062
|
Chris@16
|
1063 // the infix_node_d[] make no sense for nodes with no subnodes
|
Chris@16
|
1064 BOOST_SPIRIT_ASSERT(tree_size >= 1);
|
Chris@16
|
1065
|
Chris@16
|
1066 bool keep = true;
|
Chris@16
|
1067 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
1068 new_children.reserve((tree_size+1)/2);
|
Chris@16
|
1069 #endif
|
Chris@16
|
1070 iter_t i_end = m.trees.end();
|
Chris@16
|
1071 for (iter_t i = m.trees.begin(); i != i_end; ++i)
|
Chris@16
|
1072 {
|
Chris@16
|
1073 if (keep) {
|
Chris@16
|
1074 // adjust the length
|
Chris@16
|
1075 length += std::distance((*i).value.begin(), (*i).value.end());
|
Chris@16
|
1076
|
Chris@16
|
1077 // move the child node
|
Chris@16
|
1078 new_children.push_back(value_t());
|
Chris@16
|
1079 swap(new_children.back(), *i);
|
Chris@16
|
1080 keep = false;
|
Chris@16
|
1081 }
|
Chris@16
|
1082 else {
|
Chris@16
|
1083 // ignore this child node
|
Chris@16
|
1084 keep = true;
|
Chris@16
|
1085 }
|
Chris@16
|
1086 }
|
Chris@16
|
1087
|
Chris@16
|
1088 m = MatchT(length, new_children);
|
Chris@16
|
1089 }
|
Chris@16
|
1090 };
|
Chris@16
|
1091
|
Chris@16
|
1092 const node_parser_gen<infix_node_op> infix_node_d =
|
Chris@16
|
1093 node_parser_gen<infix_node_op>();
|
Chris@16
|
1094
|
Chris@16
|
1095 struct discard_first_node_op
|
Chris@16
|
1096 {
|
Chris@16
|
1097 template <typename MatchT>
|
Chris@16
|
1098 void operator()(MatchT& m) const
|
Chris@16
|
1099 {
|
Chris@16
|
1100 typedef typename MatchT::container_t container_t;
|
Chris@16
|
1101 typedef typename MatchT::container_t::iterator iter_t;
|
Chris@16
|
1102 typedef typename MatchT::container_t::value_type value_t;
|
Chris@16
|
1103
|
Chris@16
|
1104 using std::swap;
|
Chris@16
|
1105 using boost::swap;
|
Chris@16
|
1106 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1107
|
Chris@16
|
1108 // copying the tree nodes is expensive, since it may copy a whole
|
Chris@16
|
1109 // tree. swapping them is cheap, so swap the nodes we want into
|
Chris@16
|
1110 // a new container of children, instead of saying
|
Chris@16
|
1111 // m.trees.erase(m.trees.begin()) because, on a container_t that will
|
Chris@16
|
1112 // cause all the nodes afterwards to be copied into the previous
|
Chris@16
|
1113 // position.
|
Chris@16
|
1114 container_t new_children;
|
Chris@16
|
1115 std::size_t length = 0;
|
Chris@16
|
1116 std::size_t tree_size = m.trees.size();
|
Chris@16
|
1117
|
Chris@16
|
1118 // the discard_first_node_d[] make no sense for nodes with no subnodes
|
Chris@16
|
1119 BOOST_SPIRIT_ASSERT(tree_size >= 1);
|
Chris@16
|
1120
|
Chris@16
|
1121 if (tree_size > 1) {
|
Chris@16
|
1122 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
1123 new_children.reserve(tree_size - 1);
|
Chris@16
|
1124 #endif
|
Chris@16
|
1125 iter_t i = m.trees.begin(), i_end = m.trees.end();
|
Chris@16
|
1126 for (++i; i != i_end; ++i)
|
Chris@16
|
1127 {
|
Chris@16
|
1128 // adjust the length
|
Chris@16
|
1129 length += std::distance((*i).value.begin(), (*i).value.end());
|
Chris@16
|
1130
|
Chris@16
|
1131 // move the child node
|
Chris@16
|
1132 new_children.push_back(value_t());
|
Chris@16
|
1133 swap(new_children.back(), *i);
|
Chris@16
|
1134 }
|
Chris@16
|
1135 }
|
Chris@16
|
1136 else {
|
Chris@16
|
1137 // if there was a tree and now there isn't any, insert an empty node
|
Chris@16
|
1138 iter_t i = m.trees.begin();
|
Chris@16
|
1139
|
Chris@16
|
1140 // This isn't entirely correct, since the empty node will reference
|
Chris@16
|
1141 // the end of the discarded node, but I currently don't see any way to
|
Chris@16
|
1142 // get at the begin of the node following this subnode.
|
Chris@16
|
1143 // This should be safe anyway because the it shouldn't get dereferenced
|
Chris@16
|
1144 // under any circumstances.
|
Chris@16
|
1145 typedef typename value_t::parse_node_t::iterator_t iterator_type;
|
Chris@16
|
1146 iterator_type it = (*i).value.end();
|
Chris@16
|
1147
|
Chris@16
|
1148 new_children.push_back(
|
Chris@16
|
1149 value_t(typename value_t::parse_node_t(it, it)));
|
Chris@16
|
1150 }
|
Chris@16
|
1151
|
Chris@16
|
1152 m = MatchT(length, new_children);
|
Chris@16
|
1153 }
|
Chris@16
|
1154 };
|
Chris@16
|
1155
|
Chris@16
|
1156 const node_parser_gen<discard_first_node_op> discard_first_node_d =
|
Chris@16
|
1157 node_parser_gen<discard_first_node_op>();
|
Chris@16
|
1158
|
Chris@16
|
1159 struct discard_last_node_op
|
Chris@16
|
1160 {
|
Chris@16
|
1161 template <typename MatchT>
|
Chris@16
|
1162 void operator()(MatchT& m) const
|
Chris@16
|
1163 {
|
Chris@16
|
1164 typedef typename MatchT::container_t container_t;
|
Chris@16
|
1165 typedef typename MatchT::container_t::iterator iter_t;
|
Chris@16
|
1166 typedef typename MatchT::container_t::value_type value_t;
|
Chris@16
|
1167
|
Chris@16
|
1168 using std::swap;
|
Chris@16
|
1169 using boost::swap;
|
Chris@16
|
1170 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1171
|
Chris@16
|
1172 // copying the tree nodes is expensive, since it may copy a whole
|
Chris@16
|
1173 // tree. swapping them is cheap, so swap the nodes we want into
|
Chris@16
|
1174 // a new container of children, instead of saying
|
Chris@16
|
1175 // m.trees.erase(m.trees.begin()) because, on a container_t that will
|
Chris@16
|
1176 // cause all the nodes afterwards to be copied into the previous
|
Chris@16
|
1177 // position.
|
Chris@16
|
1178 container_t new_children;
|
Chris@16
|
1179 std::size_t length = 0;
|
Chris@16
|
1180 std::size_t tree_size = m.trees.size();
|
Chris@16
|
1181
|
Chris@16
|
1182 // the discard_last_node_d[] make no sense for nodes with no subnodes
|
Chris@16
|
1183 BOOST_SPIRIT_ASSERT(tree_size >= 1);
|
Chris@16
|
1184
|
Chris@16
|
1185 if (tree_size > 1) {
|
Chris@16
|
1186 m.trees.pop_back();
|
Chris@16
|
1187 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
1188 new_children.reserve(tree_size - 1);
|
Chris@16
|
1189 #endif
|
Chris@16
|
1190 iter_t i_end = m.trees.end();
|
Chris@16
|
1191 for (iter_t i = m.trees.begin(); i != i_end; ++i)
|
Chris@16
|
1192 {
|
Chris@16
|
1193 // adjust the length
|
Chris@16
|
1194 length += std::distance((*i).value.begin(), (*i).value.end());
|
Chris@16
|
1195
|
Chris@16
|
1196 // move the child node
|
Chris@16
|
1197 new_children.push_back(value_t());
|
Chris@16
|
1198 swap(new_children.back(), *i);
|
Chris@16
|
1199 }
|
Chris@16
|
1200 }
|
Chris@16
|
1201 else {
|
Chris@16
|
1202 // if there was a tree and now there isn't any, insert an empty node
|
Chris@16
|
1203 iter_t i = m.trees.begin();
|
Chris@16
|
1204
|
Chris@16
|
1205 typedef typename value_t::parse_node_t::iterator_t iterator_type;
|
Chris@16
|
1206 iterator_type it = (*i).value.begin();
|
Chris@16
|
1207
|
Chris@16
|
1208 new_children.push_back(
|
Chris@16
|
1209 value_t(typename value_t::parse_node_t(it, it)));
|
Chris@16
|
1210 }
|
Chris@16
|
1211
|
Chris@16
|
1212 m = MatchT(length, new_children);
|
Chris@16
|
1213 }
|
Chris@16
|
1214 };
|
Chris@16
|
1215
|
Chris@16
|
1216 const node_parser_gen<discard_last_node_op> discard_last_node_d =
|
Chris@16
|
1217 node_parser_gen<discard_last_node_op>();
|
Chris@16
|
1218
|
Chris@16
|
1219 struct inner_node_op
|
Chris@16
|
1220 {
|
Chris@16
|
1221 template <typename MatchT>
|
Chris@16
|
1222 void operator()(MatchT& m) const
|
Chris@16
|
1223 {
|
Chris@16
|
1224 typedef typename MatchT::container_t container_t;
|
Chris@16
|
1225 typedef typename MatchT::container_t::iterator iter_t;
|
Chris@16
|
1226 typedef typename MatchT::container_t::value_type value_t;
|
Chris@16
|
1227
|
Chris@16
|
1228 using std::swap;
|
Chris@16
|
1229 using boost::swap;
|
Chris@16
|
1230 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1231
|
Chris@16
|
1232 // copying the tree nodes is expensive, since it may copy a whole
|
Chris@16
|
1233 // tree. swapping them is cheap, so swap the nodes we want into
|
Chris@16
|
1234 // a new container of children, instead of saying
|
Chris@16
|
1235 // m.trees.erase(m.trees.begin()) because, on a container_t that will
|
Chris@16
|
1236 // cause all the nodes afterwards to be copied into the previous
|
Chris@16
|
1237 // position.
|
Chris@16
|
1238 container_t new_children;
|
Chris@16
|
1239 std::size_t length = 0;
|
Chris@16
|
1240 std::size_t tree_size = m.trees.size();
|
Chris@16
|
1241
|
Chris@16
|
1242 // the inner_node_d[] make no sense for nodes with less then 2 subnodes
|
Chris@16
|
1243 BOOST_SPIRIT_ASSERT(tree_size >= 2);
|
Chris@16
|
1244
|
Chris@16
|
1245 if (tree_size > 2) {
|
Chris@16
|
1246 m.trees.pop_back(); // erase the last element
|
Chris@16
|
1247 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
|
Chris@16
|
1248 new_children.reserve(tree_size - 1);
|
Chris@16
|
1249 #endif
|
Chris@16
|
1250 iter_t i = m.trees.begin(); // skip over the first element
|
Chris@16
|
1251 iter_t i_end = m.trees.end();
|
Chris@16
|
1252 for (++i; i != i_end; ++i)
|
Chris@16
|
1253 {
|
Chris@16
|
1254 // adjust the length
|
Chris@16
|
1255 length += std::distance((*i).value.begin(), (*i).value.end());
|
Chris@16
|
1256
|
Chris@16
|
1257 // move the child node
|
Chris@16
|
1258 new_children.push_back(value_t());
|
Chris@16
|
1259 swap(new_children.back(), *i);
|
Chris@16
|
1260 }
|
Chris@16
|
1261 }
|
Chris@16
|
1262 else {
|
Chris@16
|
1263 // if there was a tree and now there isn't any, insert an empty node
|
Chris@16
|
1264 iter_t i = m.trees.begin(); // skip over the first element
|
Chris@16
|
1265
|
Chris@16
|
1266 typedef typename value_t::parse_node_t::iterator_t iterator_type;
|
Chris@16
|
1267 iterator_type it = (*++i).value.begin();
|
Chris@16
|
1268
|
Chris@16
|
1269 new_children.push_back(
|
Chris@16
|
1270 value_t(typename value_t::parse_node_t(it, it)));
|
Chris@16
|
1271 }
|
Chris@16
|
1272
|
Chris@16
|
1273 m = MatchT(length, new_children);
|
Chris@16
|
1274 }
|
Chris@16
|
1275 };
|
Chris@16
|
1276
|
Chris@16
|
1277 const node_parser_gen<inner_node_op> inner_node_d =
|
Chris@16
|
1278 node_parser_gen<inner_node_op>();
|
Chris@16
|
1279
|
Chris@16
|
1280
|
Chris@16
|
1281 //////////////////////////////////
|
Chris@16
|
1282 // action_directive_parser and action_directive_parser_gen
|
Chris@16
|
1283 // are meant to be used as a template to create directives that
|
Chris@16
|
1284 // generate action classes. For example access_match and
|
Chris@16
|
1285 // access_node. The ActionParserT template parameter must be
|
Chris@16
|
1286 // a class that has an innter class called action that is templated
|
Chris@16
|
1287 // on the parser type and the action type.
|
Chris@16
|
1288 template <typename ActionParserT>
|
Chris@16
|
1289 struct action_directive_parser_gen;
|
Chris@16
|
1290
|
Chris@16
|
1291 template <typename T, typename ActionParserT>
|
Chris@16
|
1292 struct action_directive_parser
|
Chris@16
|
1293 : public unary<T, parser<action_directive_parser<T, ActionParserT> > >
|
Chris@16
|
1294 {
|
Chris@16
|
1295 typedef action_directive_parser<T, ActionParserT> self_t;
|
Chris@16
|
1296 typedef action_directive_parser_gen<ActionParserT> parser_generator_t;
|
Chris@16
|
1297 typedef unary_parser_category parser_category_t;
|
Chris@16
|
1298
|
Chris@16
|
1299 action_directive_parser(T const& a)
|
Chris@16
|
1300 : unary<T, parser<action_directive_parser<T, ActionParserT> > >(a) {}
|
Chris@16
|
1301
|
Chris@16
|
1302 template <typename ScannerT>
|
Chris@16
|
1303 struct result
|
Chris@16
|
1304 {
|
Chris@16
|
1305 typedef typename parser_result<T, ScannerT>::type type;
|
Chris@16
|
1306 };
|
Chris@16
|
1307
|
Chris@16
|
1308 template <typename ScannerT>
|
Chris@16
|
1309 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
1310 parse(ScannerT const& scanner) const
|
Chris@16
|
1311 {
|
Chris@16
|
1312 return this->subject().parse(scanner);
|
Chris@16
|
1313 }
|
Chris@16
|
1314
|
Chris@16
|
1315 template <typename ActionT>
|
Chris@16
|
1316 typename ActionParserT::template action<action_directive_parser<T, ActionParserT>, ActionT>
|
Chris@16
|
1317 operator[](ActionT const& actor) const
|
Chris@16
|
1318 {
|
Chris@16
|
1319 typedef typename
|
Chris@16
|
1320 ActionParserT::template action<action_directive_parser, ActionT>
|
Chris@16
|
1321 action_t;
|
Chris@16
|
1322 return action_t(*this, actor);
|
Chris@16
|
1323 }
|
Chris@16
|
1324 };
|
Chris@16
|
1325
|
Chris@16
|
1326 //////////////////////////////////
|
Chris@16
|
1327 template <typename ActionParserT>
|
Chris@16
|
1328 struct action_directive_parser_gen
|
Chris@16
|
1329 {
|
Chris@16
|
1330 template <typename T>
|
Chris@16
|
1331 struct result {
|
Chris@16
|
1332
|
Chris@16
|
1333 typedef action_directive_parser<T, ActionParserT> type;
|
Chris@16
|
1334 };
|
Chris@16
|
1335
|
Chris@16
|
1336 template <typename T>
|
Chris@16
|
1337 static action_directive_parser<T, ActionParserT>
|
Chris@16
|
1338 generate(parser<T> const& s)
|
Chris@16
|
1339 {
|
Chris@16
|
1340 return action_directive_parser<T, ActionParserT>(s.derived());
|
Chris@16
|
1341 }
|
Chris@16
|
1342
|
Chris@16
|
1343 template <typename T>
|
Chris@16
|
1344 action_directive_parser<T, ActionParserT>
|
Chris@16
|
1345 operator[](parser<T> const& s) const
|
Chris@16
|
1346 {
|
Chris@16
|
1347 return action_directive_parser<T, ActionParserT>(s.derived());
|
Chris@16
|
1348 }
|
Chris@16
|
1349 };
|
Chris@16
|
1350
|
Chris@16
|
1351 //////////////////////////////////
|
Chris@16
|
1352 // Calls the attached action passing it the match from the parser
|
Chris@16
|
1353 // and the first and last iterators.
|
Chris@16
|
1354 // The inner template class is used to simulate template-template parameters
|
Chris@16
|
1355 // (declared in common_fwd.hpp).
|
Chris@16
|
1356 template <typename ParserT, typename ActionT>
|
Chris@16
|
1357 struct access_match_action::action
|
Chris@16
|
1358 : public unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >
|
Chris@16
|
1359 {
|
Chris@16
|
1360 typedef action_parser_category parser_category;
|
Chris@16
|
1361 typedef action<ParserT, ActionT> self_t;
|
Chris@16
|
1362
|
Chris@16
|
1363 template <typename ScannerT>
|
Chris@16
|
1364 struct result
|
Chris@16
|
1365 {
|
Chris@16
|
1366 typedef typename parser_result<ParserT, ScannerT>::type type;
|
Chris@16
|
1367 };
|
Chris@16
|
1368
|
Chris@16
|
1369 action( ParserT const& subject,
|
Chris@16
|
1370 ActionT const& actor_);
|
Chris@16
|
1371
|
Chris@16
|
1372 template <typename ScannerT>
|
Chris@16
|
1373 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
1374 parse(ScannerT const& scanner) const;
|
Chris@16
|
1375
|
Chris@16
|
1376 ActionT const &predicate() const;
|
Chris@16
|
1377
|
Chris@16
|
1378 private:
|
Chris@16
|
1379 ActionT actor;
|
Chris@16
|
1380 };
|
Chris@16
|
1381
|
Chris@16
|
1382 //////////////////////////////////
|
Chris@16
|
1383 template <typename ParserT, typename ActionT>
|
Chris@16
|
1384 access_match_action::action<ParserT, ActionT>::action(
|
Chris@16
|
1385 ParserT const& subject,
|
Chris@16
|
1386 ActionT const& actor_)
|
Chris@16
|
1387 : unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >(subject)
|
Chris@16
|
1388 , actor(actor_)
|
Chris@16
|
1389 {}
|
Chris@16
|
1390
|
Chris@16
|
1391 //////////////////////////////////
|
Chris@16
|
1392 template <typename ParserT, typename ActionT>
|
Chris@16
|
1393 template <typename ScannerT>
|
Chris@16
|
1394 typename parser_result<access_match_action::action<ParserT, ActionT>, ScannerT>::type
|
Chris@16
|
1395 access_match_action::action<ParserT, ActionT>::
|
Chris@16
|
1396 parse(ScannerT const& scan) const
|
Chris@16
|
1397 {
|
Chris@16
|
1398 typedef typename ScannerT::iterator_t iterator_t;
|
Chris@16
|
1399 typedef typename parser_result<self_t, ScannerT>::type result_t;
|
Chris@16
|
1400 if (!scan.at_end())
|
Chris@16
|
1401 {
|
Chris@16
|
1402 iterator_t save = scan.first;
|
Chris@16
|
1403 result_t hit = this->subject().parse(scan);
|
Chris@16
|
1404 actor(hit, save, scan.first);
|
Chris@16
|
1405 return hit;
|
Chris@16
|
1406 }
|
Chris@16
|
1407 return scan.no_match();
|
Chris@16
|
1408 }
|
Chris@16
|
1409
|
Chris@16
|
1410 //////////////////////////////////
|
Chris@16
|
1411 template <typename ParserT, typename ActionT>
|
Chris@16
|
1412 ActionT const &access_match_action::action<ParserT, ActionT>::predicate() const
|
Chris@16
|
1413 {
|
Chris@16
|
1414 return actor;
|
Chris@16
|
1415 }
|
Chris@16
|
1416
|
Chris@16
|
1417 //////////////////////////////////
|
Chris@16
|
1418 const action_directive_parser_gen<access_match_action> access_match_d
|
Chris@16
|
1419 = action_directive_parser_gen<access_match_action>();
|
Chris@16
|
1420
|
Chris@16
|
1421
|
Chris@16
|
1422
|
Chris@16
|
1423 //////////////////////////////////
|
Chris@16
|
1424 // Calls the attached action passing it the node from the parser
|
Chris@16
|
1425 // and the first and last iterators
|
Chris@16
|
1426 // The inner template class is used to simulate template-template parameters
|
Chris@16
|
1427 // (declared in common_fwd.hpp).
|
Chris@16
|
1428 template <typename ParserT, typename ActionT>
|
Chris@16
|
1429 struct access_node_action::action
|
Chris@16
|
1430 : public unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >
|
Chris@16
|
1431 {
|
Chris@16
|
1432 typedef action_parser_category parser_category;
|
Chris@16
|
1433 typedef action<ParserT, ActionT> self_t;
|
Chris@16
|
1434
|
Chris@16
|
1435 template <typename ScannerT>
|
Chris@16
|
1436 struct result
|
Chris@16
|
1437 {
|
Chris@16
|
1438 typedef typename parser_result<ParserT, ScannerT>::type type;
|
Chris@16
|
1439 };
|
Chris@16
|
1440
|
Chris@16
|
1441 action( ParserT const& subject,
|
Chris@16
|
1442 ActionT const& actor_);
|
Chris@16
|
1443
|
Chris@16
|
1444 template <typename ScannerT>
|
Chris@16
|
1445 typename parser_result<self_t, ScannerT>::type
|
Chris@16
|
1446 parse(ScannerT const& scanner) const;
|
Chris@16
|
1447
|
Chris@16
|
1448 ActionT const &predicate() const;
|
Chris@16
|
1449
|
Chris@16
|
1450 private:
|
Chris@16
|
1451 ActionT actor;
|
Chris@16
|
1452 };
|
Chris@16
|
1453
|
Chris@16
|
1454 //////////////////////////////////
|
Chris@16
|
1455 template <typename ParserT, typename ActionT>
|
Chris@16
|
1456 access_node_action::action<ParserT, ActionT>::action(
|
Chris@16
|
1457 ParserT const& subject,
|
Chris@16
|
1458 ActionT const& actor_)
|
Chris@16
|
1459 : unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >(subject)
|
Chris@16
|
1460 , actor(actor_)
|
Chris@16
|
1461 {}
|
Chris@16
|
1462
|
Chris@16
|
1463 //////////////////////////////////
|
Chris@16
|
1464 template <typename ParserT, typename ActionT>
|
Chris@16
|
1465 template <typename ScannerT>
|
Chris@16
|
1466 typename parser_result<access_node_action::action<ParserT, ActionT>, ScannerT>::type
|
Chris@16
|
1467 access_node_action::action<ParserT, ActionT>::
|
Chris@16
|
1468 parse(ScannerT const& scan) const
|
Chris@16
|
1469 {
|
Chris@16
|
1470 typedef typename ScannerT::iterator_t iterator_t;
|
Chris@16
|
1471 typedef typename parser_result<self_t, ScannerT>::type result_t;
|
Chris@16
|
1472 if (!scan.at_end())
|
Chris@16
|
1473 {
|
Chris@16
|
1474 iterator_t save = scan.first;
|
Chris@16
|
1475 result_t hit = this->subject().parse(scan);
|
Chris@16
|
1476 if (hit && hit.trees.size() > 0)
|
Chris@16
|
1477 actor(*hit.trees.begin(), save, scan.first);
|
Chris@16
|
1478 return hit;
|
Chris@16
|
1479 }
|
Chris@16
|
1480 return scan.no_match();
|
Chris@16
|
1481 }
|
Chris@16
|
1482
|
Chris@16
|
1483 //////////////////////////////////
|
Chris@16
|
1484 template <typename ParserT, typename ActionT>
|
Chris@16
|
1485 ActionT const &access_node_action::action<ParserT, ActionT>::predicate() const
|
Chris@16
|
1486 {
|
Chris@16
|
1487 return actor;
|
Chris@16
|
1488 }
|
Chris@16
|
1489
|
Chris@16
|
1490 //////////////////////////////////
|
Chris@16
|
1491 const action_directive_parser_gen<access_node_action> access_node_d
|
Chris@16
|
1492 = action_directive_parser_gen<access_node_action>();
|
Chris@16
|
1493
|
Chris@16
|
1494
|
Chris@16
|
1495
|
Chris@16
|
1496 //////////////////////////////////
|
Chris@16
|
1497
|
Chris@16
|
1498 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1499 //
|
Chris@16
|
1500 // tree_parse_info
|
Chris@16
|
1501 //
|
Chris@16
|
1502 // Results returned by the tree parse functions:
|
Chris@16
|
1503 //
|
Chris@16
|
1504 // stop: points to the final parse position (i.e parsing
|
Chris@16
|
1505 // processed the input up to this point).
|
Chris@16
|
1506 //
|
Chris@16
|
1507 // match: true if parsing is successful. This may be full:
|
Chris@16
|
1508 // the parser consumed all the input, or partial:
|
Chris@16
|
1509 // the parser consumed only a portion of the input.
|
Chris@16
|
1510 //
|
Chris@16
|
1511 // full: true when we have a full match (i.e the parser
|
Chris@16
|
1512 // consumed all the input.
|
Chris@16
|
1513 //
|
Chris@16
|
1514 // length: The number of characters consumed by the parser.
|
Chris@16
|
1515 // This is valid only if we have a successful match
|
Chris@16
|
1516 // (either partial or full). A negative value means
|
Chris@16
|
1517 // that the match is unsucessful.
|
Chris@16
|
1518 //
|
Chris@16
|
1519 // trees: Contains the root node(s) of the tree.
|
Chris@16
|
1520 //
|
Chris@16
|
1521 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1522 template <
|
Chris@16
|
1523 typename IteratorT,
|
Chris@16
|
1524 typename NodeFactoryT,
|
Chris@16
|
1525 typename T
|
Chris@16
|
1526 >
|
Chris@16
|
1527 struct tree_parse_info
|
Chris@16
|
1528 {
|
Chris@16
|
1529 IteratorT stop;
|
Chris@16
|
1530 bool match;
|
Chris@16
|
1531 bool full;
|
Chris@16
|
1532 std::size_t length;
|
Chris@16
|
1533 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees;
|
Chris@16
|
1534
|
Chris@16
|
1535 tree_parse_info()
|
Chris@16
|
1536 : stop()
|
Chris@16
|
1537 , match(false)
|
Chris@16
|
1538 , full(false)
|
Chris@16
|
1539 , length(0)
|
Chris@16
|
1540 , trees()
|
Chris@16
|
1541 {}
|
Chris@16
|
1542
|
Chris@16
|
1543 template <typename IteratorT2>
|
Chris@16
|
1544 tree_parse_info(tree_parse_info<IteratorT2> const& pi)
|
Chris@16
|
1545 : stop(pi.stop)
|
Chris@16
|
1546 , match(pi.match)
|
Chris@16
|
1547 , full(pi.full)
|
Chris@16
|
1548 , length(pi.length)
|
Chris@16
|
1549 , trees()
|
Chris@16
|
1550 {
|
Chris@16
|
1551 using std::swap;
|
Chris@16
|
1552 using boost::swap;
|
Chris@16
|
1553 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1554
|
Chris@16
|
1555 // use auto_ptr like ownership for the trees data member
|
Chris@16
|
1556 swap(trees, pi.trees);
|
Chris@16
|
1557 }
|
Chris@16
|
1558
|
Chris@16
|
1559 tree_parse_info(
|
Chris@16
|
1560 IteratorT stop_,
|
Chris@16
|
1561 bool match_,
|
Chris@16
|
1562 bool full_,
|
Chris@16
|
1563 std::size_t length_,
|
Chris@16
|
1564 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees_)
|
Chris@16
|
1565 : stop(stop_)
|
Chris@16
|
1566 , match(match_)
|
Chris@16
|
1567 , full(full_)
|
Chris@16
|
1568 , length(length_)
|
Chris@16
|
1569 , trees()
|
Chris@16
|
1570 {
|
Chris@16
|
1571 using std::swap;
|
Chris@16
|
1572 using boost::swap;
|
Chris@16
|
1573 using BOOST_SPIRIT_CLASSIC_NS::swap;
|
Chris@16
|
1574
|
Chris@16
|
1575 // use auto_ptr like ownership for the trees data member
|
Chris@16
|
1576 swap(trees, trees_);
|
Chris@16
|
1577 }
|
Chris@16
|
1578 };
|
Chris@16
|
1579
|
Chris@16
|
1580 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
|
Chris@16
|
1581
|
Chris@16
|
1582 }} // namespace BOOST_SPIRIT_CLASSIC_NS
|
Chris@16
|
1583
|
Chris@16
|
1584 #endif
|
Chris@16
|
1585
|