First public contribution.
1 /*=============================================================================
2 Copyright (c) 2001-2003 Daniel Nuffer
3 http://spirit.sourceforge.net/
5 Use, modification and distribution is subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #ifndef BOOST_SPIRIT_TREE_COMMON_HPP
10 #define BOOST_SPIRIT_TREE_COMMON_HPP
12 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
18 #if defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
19 #include <boost/pool/pool_alloc.hpp>
24 #include <boost/ref.hpp>
25 #include <boost/call_traits.hpp>
26 #include <boost/spirit/core.hpp>
27 #include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
29 #if defined(BOOST_SPIRIT_DEBUG) && \
30 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
32 #include <boost/spirit/debug/debug_node.hpp>
35 #include <boost/spirit/tree/common_fwd.hpp>
37 namespace boost { namespace spirit {
40 void swap(tree_node<T>& a, tree_node<T>& b);
42 template <typename T, typename V>
43 void swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b);
47 inline void cp_swap(T& t1, T& t2);
53 typedef T parse_node_t;
55 #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
56 typedef std::allocator<tree_node<T> > allocator_type;
57 #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
58 typedef boost::pool_allocator<tree_node<T> > allocator_type;
60 typedef boost::fast_pool_allocator<tree_node<T> > allocator_type;
63 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
64 typedef std::vector<tree_node<T>, allocator_type> children_t;
66 typedef std::list<tree_node<T>, allocator_type> children_t;
67 #endif // BOOST_SPIRIT_USE_LIST_FOR_TREES
69 typedef typename children_t::iterator tree_iterator;
70 typedef typename children_t::const_iterator const_tree_iterator;
80 explicit tree_node(T const& v)
85 tree_node(T const& v, children_t const& c)
90 void swap(tree_node<T>& x)
92 impl::cp_swap(value, x.value);
93 impl::cp_swap(children, x.children);
96 // Intel V5.0.1 has a problem without this explicit operator=
97 tree_node &operator= (tree_node const &rhs)
99 tree_node(rhs).swap(*this);
104 #if defined(BOOST_SPIRIT_DEBUG) && \
105 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
106 template <typename T>
108 operator<<(std::ostream& o, tree_node<T> const& n)
110 static int depth = 0;
112 for (int i = 0; i <= depth; ++i)
116 o << "(depth = " << depth++ << " value = " << n.value;
118 for (typename tree_node<T>::children_t::const_iterator it = n.children.begin();
119 it != n.children.end(); ++it)
121 o << " children[" << c++ << "] = " << *it;
129 //////////////////////////////////
130 template <typename IteratorT, typename ValueT>
131 struct node_iter_data
133 typedef IteratorT iterator_t;
134 typedef IteratorT /*const*/ const_iterator_t;
137 : first(), last(), is_root_(false), parser_id_(), value_()
140 node_iter_data(IteratorT const& _first, IteratorT const& _last)
141 : first(_first), last(_last), is_root_(false), parser_id_(), value_()
144 void swap(node_iter_data& x)
146 impl::cp_swap(first, x.first);
147 impl::cp_swap(last, x.last);
148 impl::cp_swap(parser_id_, x.parser_id_);
149 impl::cp_swap(is_root_, x.is_root_);
150 impl::cp_swap(value_, x.value_);
158 IteratorT const& begin() const
168 IteratorT const& end() const
193 ValueT const& value() const
198 void value(ValueT const& v)
203 IteratorT first, last;
205 parser_id parser_id_;
211 #if defined(BOOST_SPIRIT_DEBUG) && \
212 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
213 // value is default nil_t, so provide an operator<< for nil_t
215 operator<<(std::ostream& o, nil_t const&)
220 template <typename IteratorT, typename ValueT>
222 operator<<(std::ostream& o, node_iter_data<IteratorT, ValueT> const& n)
224 o << "(id = " << n.id() << " text = \"";
225 typedef typename node_iter_data<IteratorT, ValueT>::const_iterator_t
227 for (iterator_t it = n.begin(); it != n.end(); ++it)
228 impl::token_printer(o, *it);
229 o << "\" is_root = " << n.is_root()
230 << /*" value = " << n.value() << */")";
235 //////////////////////////////////
236 template <typename IteratorT = char const*, typename ValueT = nil_t>
240 typename boost::detail::iterator_traits<IteratorT>::value_type
243 #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
244 typedef std::allocator<value_type> allocator_type;
245 #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
246 typedef boost::pool_allocator<value_type> allocator_type;
248 typedef boost::fast_pool_allocator<value_type> allocator_type;
251 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
252 typedef std::vector<value_type, allocator_type> container_t;
254 typedef std::list<value_type, allocator_type> container_t;
257 typedef typename container_t::iterator iterator_t;
258 typedef typename container_t::const_iterator const_iterator_t;
261 : text(), is_root_(false), parser_id_(), value_()
264 #if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
265 node_val_data(IteratorT const& _first, IteratorT const& _last)
266 : text(), is_root_(false), parser_id_(), value_()
268 std::copy(_first, _last, std::inserter(text, text.end()));
271 // This constructor is for building text out of iterators
272 template <typename IteratorT2>
273 node_val_data(IteratorT2 const& _first, IteratorT2 const& _last)
274 : text(), is_root_(false), parser_id_(), value_()
276 std::copy(_first, _last, std::inserter(text, text.end()));
279 node_val_data(IteratorT const& _first, IteratorT const& _last)
280 : text(_first, _last), is_root_(false), parser_id_(), value_()
283 // This constructor is for building text out of iterators
284 template <typename IteratorT2>
285 node_val_data(IteratorT2 const& _first, IteratorT2 const& _last)
286 : text(_first, _last), is_root_(false), parser_id_(), value_()
290 void swap(node_val_data& x)
292 impl::cp_swap(text, x.text);
293 impl::cp_swap(is_root_, x.is_root_);
294 impl::cp_swap(parser_id_, x.parser_id_);
295 impl::cp_swap(value_, x.value_);
298 typename container_t::iterator begin()
303 typename container_t::const_iterator begin() const
308 typename container_t::iterator end()
313 typename container_t::const_iterator end() const
338 ValueT const& value() const
343 void value(ValueT const& v)
351 parser_id parser_id_;
355 #if defined(BOOST_SPIRIT_DEBUG) && \
356 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
357 template <typename IteratorT, typename ValueT>
359 operator<<(std::ostream& o, node_val_data<IteratorT, ValueT> const& n)
361 o << "(id = " << n.id() << " text = \"";
362 typedef typename node_val_data<IteratorT, ValueT>::const_iterator_t
364 for (iterator_t it = n.begin(); it != n.end(); ++it)
365 impl::token_printer(o, *it);
366 o << "\" is_root = " << n.is_root()
367 << " value = " << n.value() << ")";
372 template <typename T>
374 swap(tree_node<T>& a, tree_node<T>& b)
379 template <typename T, typename V>
381 swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b)
386 //////////////////////////////////
387 template <typename ValueT>
388 class node_iter_data_factory
391 // This inner class is so that node_iter_data_factory can simulate
392 // a template template parameter
393 template <typename IteratorT>
397 typedef IteratorT iterator_t;
398 typedef node_iter_data<iterator_t, ValueT> node_t;
400 static node_t create_node(iterator_t const& first, iterator_t const& last,
401 bool /*is_leaf_node*/)
403 return node_t(first, last);
406 static node_t empty_node()
411 // precondition: ContainerT contains a tree_node<node_t>. And all
412 // iterators in the container point to the same sequence.
413 template <typename ContainerT>
414 static node_t group_nodes(ContainerT const& nodes)
416 return node_t(nodes.begin()->value.begin(),
417 nodes.back().value.end());
422 //////////////////////////////////
423 template <typename ValueT>
424 class node_val_data_factory
427 // This inner class is so that node_val_data_factory can simulate
428 // a template template parameter
429 template <typename IteratorT>
433 typedef IteratorT iterator_t;
434 typedef node_val_data<iterator_t, ValueT> node_t;
436 static node_t create_node(iterator_t const& first, iterator_t const& last,
440 return node_t(first, last);
445 static node_t empty_node()
450 template <typename ContainerT>
451 static node_t group_nodes(ContainerT const& nodes)
453 typename node_t::container_t c;
454 typename ContainerT::const_iterator i_end = nodes.end();
455 // copy all the nodes text into a new one
456 for (typename ContainerT::const_iterator i = nodes.begin();
459 // See docs: token_node_d or leaf_node_d cannot be used with a
460 // rule inside the [].
461 assert(i->children.size() == 0);
462 c.insert(c.end(), i->value.begin(), i->value.end());
464 return node_t(c.begin(), c.end());
469 //////////////////////////////////
470 template <typename ValueT>
471 class node_all_val_data_factory
474 // This inner class is so that node_all_val_data_factory can simulate
475 // a template template parameter
476 template <typename IteratorT>
480 typedef IteratorT iterator_t;
481 typedef node_val_data<iterator_t, ValueT> node_t;
483 static node_t create_node(iterator_t const& first, iterator_t const& last,
484 bool /*is_leaf_node*/)
486 return node_t(first, last);
489 static node_t empty_node()
494 template <typename ContainerT>
495 static node_t group_nodes(ContainerT const& nodes)
497 typename node_t::container_t c;
498 typename ContainerT::const_iterator i_end = nodes.end();
499 // copy all the nodes text into a new one
500 for (typename ContainerT::const_iterator i = nodes.begin();
503 // See docs: token_node_d or leaf_node_d cannot be used with a
504 // rule inside the [].
505 assert(i->children.size() == 0);
506 c.insert(c.end(), i->value.begin(), i->value.end());
508 return node_t(c.begin(), c.end());
515 ///////////////////////////////////////////////////////////////////////////
516 // can't call unqualified swap from within classname::swap
517 // as Koenig lookup rules will find only the classname::swap
518 // member function not the global declaration, so use cp_swap
519 // as a forwarding function (JM):
523 template <typename T>
524 inline void cp_swap(T& t1, T& t2)
527 using boost::spirit::swap;
533 //////////////////////////////////
534 template <typename IteratorT, typename NodeFactoryT, typename T>
535 class tree_match : public match<T>
539 typedef typename NodeFactoryT::template factory<IteratorT> node_factory_t;
540 typedef typename node_factory_t::node_t parse_node_t;
541 typedef tree_node<parse_node_t> node_t;
542 typedef typename node_t::children_t container_t;
543 typedef typename container_t::iterator tree_iterator;
544 typedef typename container_t::const_iterator const_tree_iterator;
547 typedef typename boost::call_traits<T>::param_type param_type;
548 typedef typename boost::call_traits<T>::reference reference;
549 typedef typename boost::call_traits<T>::const_reference const_reference;
552 : match<T>(), trees()
556 tree_match(std::size_t length)
557 : match<T>(length), trees()
560 tree_match(std::size_t length, parse_node_t const& n)
561 : match<T>(length), trees()
563 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
564 trees.reserve(10); // this is more or less an arbitrary number...
566 trees.push_back(node_t(n));
569 tree_match(std::size_t length, param_type val, parse_node_t const& n)
570 : match<T>(length, val), trees()
572 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
573 trees.reserve(10); // this is more or less an arbitrary number...
575 trees.push_back(node_t(n));
578 // attention, these constructors will change the second parameter!
579 tree_match(std::size_t length, container_t& c)
580 : match<T>(length), trees()
582 impl::cp_swap(trees, c);
585 tree_match(std::size_t length, param_type val, container_t& c)
586 : match<T>(length, val), trees()
588 impl::cp_swap(trees, c);
591 template <typename T2>
592 tree_match(match<T2> const& other)
593 : match<T>(other), trees()
596 template <typename T2, typename T3, typename T4>
597 tree_match(tree_match<T2, T3, T4> const& other)
598 : match<T>(other), trees()
599 { impl::cp_swap(trees, other.trees); }
601 template <typename T2>
603 operator=(match<T2> const& other)
605 match<T>::operator=(other);
609 template <typename T2, typename T3, typename T4>
611 operator=(tree_match<T2, T3, T4> const& other)
613 match<T>::operator=(other);
614 impl::cp_swap(trees, other.trees);
618 tree_match(tree_match const& x)
619 : match<T>(x), trees()
621 // use auto_ptr like ownership for the trees data member
622 impl::cp_swap(trees, x.trees);
625 tree_match& operator=(tree_match const& x)
632 void swap(tree_match& x)
635 impl::cp_swap(trees, x.trees);
638 mutable container_t trees;
641 #if defined(BOOST_SPIRIT_DEBUG) && \
642 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
643 template <typename IteratorT, typename NodeFactoryT, typename T>
645 operator<<(std::ostream& o, tree_match<IteratorT, NodeFactoryT, T> const& m)
648 typename tree_match<IteratorT, NodeFactoryT, T>::container_t::iterator
651 o << "(length = " << (int)m.length();
653 for (iterator i = m.trees.begin(); i != m.trees.end(); ++i)
655 o << " trees[" << c++ << "] = " << *i;
662 //////////////////////////////////
665 template <typename FunctorT, typename MatchT>
666 static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/)
669 template <typename MatchT, typename Iterator1T, typename Iterator2T>
670 static void group_match(MatchT& /*m*/, parser_id const& /*id*/,
671 Iterator1T const& /*first*/, Iterator2T const& /*last*/)
674 template <typename MatchT>
675 static void concat(MatchT& /*a*/, MatchT const& /*b*/)
679 //////////////////////////////////
681 typename MatchPolicyT,
683 typename NodeFactoryT,
686 struct common_tree_match_policy : public match_policy
688 common_tree_match_policy()
692 template <typename PolicyT>
693 common_tree_match_policy(PolicyT const & policies)
694 : match_policy(policies)
698 template <typename T>
699 struct result { typedef tree_match<IteratorT, NodeFactoryT, T> type; };
701 typedef tree_match<IteratorT, NodeFactoryT> match_t;
702 typedef IteratorT iterator_t;
703 typedef TreePolicyT tree_policy_t;
704 typedef NodeFactoryT factory_t;
706 static const match_t no_match() { return match_t(); }
707 static const match_t empty_match()
708 { return match_t(0, tree_policy_t::empty_node()); }
710 template <typename AttrT, typename Iterator1T, typename Iterator2T>
711 static tree_match<IteratorT, NodeFactoryT, AttrT> create_match(
714 Iterator1T const& first,
715 Iterator2T const& last)
717 #if defined(BOOST_SPIRIT_DEBUG) && \
718 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
720 BOOST_SPIRIT_DEBUG_OUT << "\n>>> create_node(begin) <<<\n"
721 "creating node text: \"";
722 for (Iterator1T it = first; it != last; ++it)
723 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
724 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
725 BOOST_SPIRIT_DEBUG_OUT << ">>> create_node(end) <<<\n\n";
727 return tree_match<IteratorT, NodeFactoryT, AttrT>(length, val,
728 tree_policy_t::create_node(length, first, last, true));
731 template <typename Match1T, typename Match2T>
732 static void concat_match(Match1T& a, Match2T const& b)
734 #if defined(BOOST_SPIRIT_DEBUG) && \
735 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
737 BOOST_SPIRIT_DEBUG_OUT << "\n>>> concat_match(begin) <<<\n";
738 BOOST_SPIRIT_DEBUG_OUT << "tree a:\n" << a << "\n";
739 BOOST_SPIRIT_DEBUG_OUT << "tree b:\n" << b << "\n";
740 BOOST_SPIRIT_DEBUG_OUT << ">>> concat_match(end) <<<\n\n";
742 BOOST_SPIRIT_ASSERT(a && b);
748 else if (b.length() == 0
749 #ifdef BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING
750 && !b.trees.begin()->value.id().to_long()
757 tree_policy_t::concat(a, b);
760 template <typename MatchT, typename IteratorT2>
765 IteratorT2 const& first,
766 IteratorT2 const& last) const
770 #if defined(BOOST_SPIRIT_DEBUG) && \
771 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_TREES)
773 BOOST_SPIRIT_DEBUG_OUT << "\n>>> group_match(begin) <<<\n"
774 "new node(" << id << ") \"";
775 for (IteratorT2 it = first; it != last; ++it)
776 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
777 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
778 BOOST_SPIRIT_DEBUG_OUT << "new child tree (before grouping):\n" << m << "\n";
780 tree_policy_t::group_match(m, id, first, last);
782 BOOST_SPIRIT_DEBUG_OUT << "new child tree (after grouping):\n" << m << "\n";
783 BOOST_SPIRIT_DEBUG_OUT << ">>> group_match(end) <<<\n\n";
785 tree_policy_t::group_match(m, id, first, last);
790 //////////////////////////////////
791 template <typename MatchPolicyT, typename NodeFactoryT>
792 struct common_tree_tree_policy
794 typedef typename MatchPolicyT::iterator_t iterator_t;
795 typedef typename MatchPolicyT::match_t match_t;
796 typedef typename NodeFactoryT::template factory<iterator_t> factory_t;
797 typedef typename factory_t::node_t node_t;
799 template <typename Iterator1T, typename Iterator2T>
801 create_node(std::size_t /*length*/, Iterator1T const& first,
802 Iterator2T const& last, bool leaf_node)
804 return factory_t::create_node(first, last, leaf_node);
810 return factory_t::empty_node();
813 template <typename FunctorT>
814 static void apply_op_to_match(FunctorT const& op, match_t& m)
820 //////////////////////////////////
821 // directives to modify how the parse tree is generated
823 struct no_tree_gen_node_parser_gen;
825 template <typename T>
826 struct no_tree_gen_node_parser
827 : public unary<T, parser<no_tree_gen_node_parser<T> > >
829 typedef no_tree_gen_node_parser<T> self_t;
830 typedef no_tree_gen_node_parser_gen parser_generator_t;
831 typedef unary_parser_category parser_category_t;
832 // typedef no_tree_gen_node_parser<T> const &embed_t;
834 no_tree_gen_node_parser(T const& a)
835 : unary<T, parser<no_tree_gen_node_parser<T> > >(a) {}
837 template <typename ScannerT>
838 typename parser_result<self_t, ScannerT>::type
839 parse(ScannerT const& scanner) const
841 typedef typename ScannerT::iteration_policy_t iteration_policy_t;
842 typedef match_policy match_policy_t;
843 typedef typename ScannerT::action_policy_t action_policy_t;
844 typedef scanner_policies<
850 return this->subject().parse(scanner.change_policies(policies_t(scanner)));
854 //////////////////////////////////
855 struct no_tree_gen_node_parser_gen
857 template <typename T>
860 typedef no_tree_gen_node_parser<T> type;
863 template <typename T>
864 static no_tree_gen_node_parser<T>
865 generate(parser<T> const& s)
867 return no_tree_gen_node_parser<T>(s.derived());
870 template <typename T>
871 no_tree_gen_node_parser<T>
872 operator[](parser<T> const& s) const
874 return no_tree_gen_node_parser<T>(s.derived());
878 //////////////////////////////////
879 const no_tree_gen_node_parser_gen no_node_d = no_tree_gen_node_parser_gen();
882 //////////////////////////////////
885 template <typename MatchPolicyT>
886 struct tree_policy_selector
888 typedef tree_policy type;
893 //////////////////////////////////
894 template <typename NodeParserT>
895 struct node_parser_gen;
897 template <typename T, typename NodeParserT>
899 : public unary<T, parser<node_parser<T, NodeParserT> > >
901 typedef node_parser<T, NodeParserT> self_t;
902 typedef node_parser_gen<NodeParserT> parser_generator_t;
903 typedef unary_parser_category parser_category_t;
904 // typedef node_parser<T, NodeParserT> const &embed_t;
906 node_parser(T const& a)
907 : unary<T, parser<node_parser<T, NodeParserT> > >(a) {}
909 template <typename ScannerT>
910 typename parser_result<self_t, ScannerT>::type
911 parse(ScannerT const& scanner) const
913 typename parser_result<self_t, ScannerT>::type hit = this->subject().parse(scanner);
916 impl::tree_policy_selector<typename ScannerT::match_policy_t>::type::apply_op_to_match(NodeParserT(), hit);
922 //////////////////////////////////
923 template <typename NodeParserT>
924 struct node_parser_gen
926 template <typename T>
929 typedef node_parser<T, NodeParserT> type;
932 template <typename T>
933 static node_parser<T, NodeParserT>
934 generate(parser<T> const& s)
936 return node_parser<T, NodeParserT>(s.derived());
939 template <typename T>
940 node_parser<T, NodeParserT>
941 operator[](parser<T> const& s) const
943 return node_parser<T, NodeParserT>(s.derived());
947 struct discard_node_op
949 template <typename MatchT>
950 void operator()(MatchT& m) const
956 const node_parser_gen<discard_node_op> discard_node_d =
957 node_parser_gen<discard_node_op>();
961 template <typename MatchT>
962 void operator()(MatchT& m) const
964 if (m.trees.size() == 1)
966 m.trees.begin()->children.clear();
968 else if (m.trees.size() > 1)
970 typedef typename MatchT::node_factory_t node_factory_t;
971 m = MatchT(m.length(), node_factory_t::group_nodes(m.trees));
976 const node_parser_gen<leaf_node_op> leaf_node_d =
977 node_parser_gen<leaf_node_op>();
978 const node_parser_gen<leaf_node_op> token_node_d =
979 node_parser_gen<leaf_node_op>();
983 template <typename MatchT>
984 void operator()(MatchT& m) const
986 typedef typename MatchT::container_t container_t;
987 typedef typename MatchT::container_t::iterator iter_t;
988 typedef typename MatchT::container_t::value_type value_t;
992 using boost::spirit::swap;
994 // copying the tree nodes is expensive, since it may copy a whole
995 // tree. swapping them is cheap, so swap the nodes we want into
996 // a new container of children.
997 container_t new_children;
998 std::size_t length = 0;
999 std::size_t tree_size = m.trees.size();
1001 // the infix_node_d[] make no sense for nodes with no subnodes
1002 BOOST_SPIRIT_ASSERT(tree_size >= 1);
1005 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1006 new_children.reserve((tree_size+1)/2);
1008 iter_t i_end = m.trees.end();
1009 for (iter_t i = m.trees.begin(); i != i_end; ++i)
1012 // adjust the length
1013 length += std::distance((*i).value.begin(), (*i).value.end());
1015 // move the child node
1016 new_children.push_back(value_t());
1017 swap(new_children.back(), *i);
1021 // ignore this child node
1026 m = MatchT(length, new_children);
1030 const node_parser_gen<infix_node_op> infix_node_d =
1031 node_parser_gen<infix_node_op>();
1033 struct discard_first_node_op
1035 template <typename MatchT>
1036 void operator()(MatchT& m) const
1038 typedef typename MatchT::container_t container_t;
1039 typedef typename MatchT::container_t::iterator iter_t;
1040 typedef typename MatchT::container_t::value_type value_t;
1044 using boost::spirit::swap;
1046 // copying the tree nodes is expensive, since it may copy a whole
1047 // tree. swapping them is cheap, so swap the nodes we want into
1048 // a new container of children, instead of saying
1049 // m.trees.erase(m.trees.begin()) because, on a container_t that will
1050 // cause all the nodes afterwards to be copied into the previous
1052 container_t new_children;
1053 std::size_t length = 0;
1054 std::size_t tree_size = m.trees.size();
1056 // the discard_first_node_d[] make no sense for nodes with no subnodes
1057 BOOST_SPIRIT_ASSERT(tree_size >= 1);
1059 if (tree_size > 1) {
1060 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1061 new_children.reserve(tree_size - 1);
1063 iter_t i = m.trees.begin(), i_end = m.trees.end();
1064 for (++i; i != i_end; ++i)
1066 // adjust the length
1067 length += std::distance((*i).value.begin(), (*i).value.end());
1069 // move the child node
1070 new_children.push_back(value_t());
1071 swap(new_children.back(), *i);
1075 // if there was a tree and now there isn't any, insert an empty node
1076 iter_t i = m.trees.begin();
1078 // This isn't entirely correct, since the empty node will reference
1079 // the end of the discarded node, but I currently don't see any way to
1080 // get at the begin of the node following this subnode.
1081 // This should be safe anyway because the it shouldn't get dereferenced
1082 // under any circumstances.
1083 typedef typename value_t::parse_node_t::iterator_t iterator_type;
1084 iterator_type it = (*i).value.end();
1086 new_children.push_back(
1087 value_t(typename value_t::parse_node_t(it, it)));
1090 m = MatchT(length, new_children);
1094 const node_parser_gen<discard_first_node_op> discard_first_node_d =
1095 node_parser_gen<discard_first_node_op>();
1097 struct discard_last_node_op
1099 template <typename MatchT>
1100 void operator()(MatchT& m) const
1102 typedef typename MatchT::container_t container_t;
1103 typedef typename MatchT::container_t::iterator iter_t;
1104 typedef typename MatchT::container_t::value_type value_t;
1108 using boost::spirit::swap;
1110 // copying the tree nodes is expensive, since it may copy a whole
1111 // tree. swapping them is cheap, so swap the nodes we want into
1112 // a new container of children, instead of saying
1113 // m.trees.erase(m.trees.begin()) because, on a container_t that will
1114 // cause all the nodes afterwards to be copied into the previous
1116 container_t new_children;
1117 std::size_t length = 0;
1118 std::size_t tree_size = m.trees.size();
1120 // the discard_last_node_d[] make no sense for nodes with no subnodes
1121 BOOST_SPIRIT_ASSERT(tree_size >= 1);
1123 if (tree_size > 1) {
1125 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1126 new_children.reserve(tree_size - 1);
1128 iter_t i_end = m.trees.end();
1129 for (iter_t i = m.trees.begin(); i != i_end; ++i)
1131 // adjust the length
1132 length += std::distance((*i).value.begin(), (*i).value.end());
1134 // move the child node
1135 new_children.push_back(value_t());
1136 swap(new_children.back(), *i);
1140 // if there was a tree and now there isn't any, insert an empty node
1141 iter_t i = m.trees.begin();
1143 typedef typename value_t::parse_node_t::iterator_t iterator_type;
1144 iterator_type it = (*i).value.begin();
1146 new_children.push_back(
1147 value_t(typename value_t::parse_node_t(it, it)));
1150 m = MatchT(length, new_children);
1154 const node_parser_gen<discard_last_node_op> discard_last_node_d =
1155 node_parser_gen<discard_last_node_op>();
1157 struct inner_node_op
1159 template <typename MatchT>
1160 void operator()(MatchT& m) const
1162 typedef typename MatchT::container_t container_t;
1163 typedef typename MatchT::container_t::iterator iter_t;
1164 typedef typename MatchT::container_t::value_type value_t;
1168 using boost::spirit::swap;
1170 // copying the tree nodes is expensive, since it may copy a whole
1171 // tree. swapping them is cheap, so swap the nodes we want into
1172 // a new container of children, instead of saying
1173 // m.trees.erase(m.trees.begin()) because, on a container_t that will
1174 // cause all the nodes afterwards to be copied into the previous
1176 container_t new_children;
1177 std::size_t length = 0;
1178 std::size_t tree_size = m.trees.size();
1180 // the inner_node_d[] make no sense for nodes with less then 2 subnodes
1181 BOOST_SPIRIT_ASSERT(tree_size >= 2);
1183 if (tree_size > 2) {
1184 m.trees.pop_back(); // erase the last element
1185 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1186 new_children.reserve(tree_size - 1);
1188 iter_t i = m.trees.begin(); // skip over the first element
1189 iter_t i_end = m.trees.end();
1190 for (++i; i != i_end; ++i)
1192 // adjust the length
1193 length += std::distance((*i).value.begin(), (*i).value.end());
1195 // move the child node
1196 new_children.push_back(value_t());
1197 swap(new_children.back(), *i);
1201 // if there was a tree and now there isn't any, insert an empty node
1202 iter_t i = m.trees.begin(); // skip over the first element
1204 typedef typename value_t::parse_node_t::iterator_t iterator_type;
1205 iterator_type it = (*++i).value.begin();
1207 new_children.push_back(
1208 value_t(typename value_t::parse_node_t(it, it)));
1211 m = MatchT(length, new_children);
1215 const node_parser_gen<inner_node_op> inner_node_d =
1216 node_parser_gen<inner_node_op>();
1219 //////////////////////////////////
1220 // action_directive_parser and action_directive_parser_gen
1221 // are meant to be used as a template to create directives that
1222 // generate action classes. For example access_match and
1223 // access_node. The ActionParserT template parameter must be
1224 // a class that has an innter class called action that is templated
1225 // on the parser type and the action type.
1226 template <typename ActionParserT>
1227 struct action_directive_parser_gen;
1229 template <typename T, typename ActionParserT>
1230 struct action_directive_parser
1231 : public unary<T, parser<action_directive_parser<T, ActionParserT> > >
1233 typedef action_directive_parser<T, ActionParserT> self_t;
1234 typedef action_directive_parser_gen<ActionParserT> parser_generator_t;
1235 typedef unary_parser_category parser_category_t;
1236 // typedef action_directive_parser<T, ActionParserT> const &embed_t;
1238 action_directive_parser(T const& a)
1239 : unary<T, parser<action_directive_parser<T, ActionParserT> > >(a) {}
1241 template <typename ScannerT>
1242 typename parser_result<self_t, ScannerT>::type
1243 parse(ScannerT const& scanner) const
1245 return this->subject().parse(scanner);
1248 template <typename ActionT>
1249 typename ActionParserT::template action<action_directive_parser<T, ActionParserT>, ActionT>
1250 operator[](ActionT const& actor) const
1253 ActionParserT::template action<action_directive_parser, ActionT>
1255 return action_t(*this, actor);
1259 //////////////////////////////////
1260 template <typename ActionParserT>
1261 struct action_directive_parser_gen
1263 template <typename T>
1266 typedef action_directive_parser<T, ActionParserT> type;
1269 template <typename T>
1270 static action_directive_parser<T, ActionParserT>
1271 generate(parser<T> const& s)
1273 return action_directive_parser<T, ActionParserT>(s.derived());
1276 template <typename T>
1277 action_directive_parser<T, ActionParserT>
1278 operator[](parser<T> const& s) const
1280 return action_directive_parser<T, ActionParserT>(s.derived());
1284 //////////////////////////////////
1285 // Calls the attached action passing it the match from the parser
1286 // and the first and last iterators.
1287 // The inner template class is used to simulate template-template parameters
1288 // (declared in common_fwd.hpp).
1289 template <typename ParserT, typename ActionT>
1290 struct access_match_action::action
1291 : public unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >
1293 typedef action_parser_category parser_category;
1294 typedef action<ParserT, ActionT> self_t;
1296 action( ParserT const& subject,
1297 ActionT const& actor_);
1299 template <typename ScannerT>
1300 typename parser_result<self_t, ScannerT>::type
1301 parse(ScannerT const& scanner) const;
1303 ActionT const &predicate() const;
1309 //////////////////////////////////
1310 template <typename ParserT, typename ActionT>
1311 access_match_action::action<ParserT, ActionT>::action(
1312 ParserT const& subject,
1313 ActionT const& actor_)
1314 : unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >(subject)
1318 //////////////////////////////////
1319 template <typename ParserT, typename ActionT>
1320 template <typename ScannerT>
1321 typename parser_result<access_match_action::action<ParserT, ActionT>, ScannerT>::type
1322 access_match_action::action<ParserT, ActionT>::
1323 parse(ScannerT const& scan) const
1325 typedef typename ScannerT::iterator_t iterator_t;
1326 typedef typename parser_result<self_t, ScannerT>::type result_t;
1329 iterator_t save = scan.first;
1330 result_t hit = this->subject().parse(scan);
1331 actor(hit, save, scan.first);
1334 return scan.no_match();
1337 //////////////////////////////////
1338 template <typename ParserT, typename ActionT>
1339 ActionT const &access_match_action::action<ParserT, ActionT>::predicate() const
1344 //////////////////////////////////
1345 const action_directive_parser_gen<access_match_action> access_match_d
1346 = action_directive_parser_gen<access_match_action>();
1350 //////////////////////////////////
1351 // Calls the attached action passing it the node from the parser
1352 // and the first and last iterators
1353 // The inner template class is used to simulate template-template parameters
1354 // (declared in common_fwd.hpp).
1355 template <typename ParserT, typename ActionT>
1356 struct access_node_action::action
1357 : public unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >
1359 typedef action_parser_category parser_category;
1360 typedef action<ParserT, ActionT> self_t;
1362 action( ParserT const& subject,
1363 ActionT const& actor_);
1365 template <typename ScannerT>
1366 typename parser_result<self_t, ScannerT>::type
1367 parse(ScannerT const& scanner) const;
1369 ActionT const &predicate() const;
1375 //////////////////////////////////
1376 template <typename ParserT, typename ActionT>
1377 access_node_action::action<ParserT, ActionT>::action(
1378 ParserT const& subject,
1379 ActionT const& actor_)
1380 : unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >(subject)
1384 //////////////////////////////////
1385 template <typename ParserT, typename ActionT>
1386 template <typename ScannerT>
1387 typename parser_result<access_node_action::action<ParserT, ActionT>, ScannerT>::type
1388 access_node_action::action<ParserT, ActionT>::
1389 parse(ScannerT const& scan) const
1391 typedef typename ScannerT::iterator_t iterator_t;
1392 typedef typename parser_result<self_t, ScannerT>::type result_t;
1395 iterator_t save = scan.first;
1396 result_t hit = this->subject().parse(scan);
1397 if (hit && hit.trees.size() > 0)
1398 actor(*hit.trees.begin(), save, scan.first);
1401 return scan.no_match();
1404 //////////////////////////////////
1405 template <typename ParserT, typename ActionT>
1406 ActionT const &access_node_action::action<ParserT, ActionT>::predicate() const
1411 //////////////////////////////////
1412 const action_directive_parser_gen<access_node_action> access_node_d
1413 = action_directive_parser_gen<access_node_action>();
1417 //////////////////////////////////
1419 ///////////////////////////////////////////////////////////////////////////////
1423 // Results returned by the tree parse functions:
1425 // stop: points to the final parse position (i.e parsing
1426 // processed the input up to this point).
1428 // match: true if parsing is successful. This may be full:
1429 // the parser consumed all the input, or partial:
1430 // the parser consumed only a portion of the input.
1432 // full: true when we have a full match (i.e the parser
1433 // consumed all the input.
1435 // length: The number of characters consumed by the parser.
1436 // This is valid only if we have a successful match
1437 // (either partial or full). A negative value means
1438 // that the match is unsucessful.
1440 // trees: Contains the root node(s) of the tree.
1442 ///////////////////////////////////////////////////////////////////////////////
1445 typename NodeFactoryT,
1448 struct tree_parse_info
1454 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees;
1464 template <typename IteratorT2>
1465 tree_parse_info(tree_parse_info<IteratorT2> const& pi)
1474 using boost::spirit::swap;
1476 // use auto_ptr like ownership for the trees data member
1477 swap(trees, pi.trees);
1484 std::size_t length_,
1485 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees_)
1494 using boost::spirit::swap;
1496 // use auto_ptr like ownership for the trees data member
1497 swap(trees, trees_);
1501 }} // namespace boost::spirit