EVOLUTION-MANAGER
Edit File: common.hpp
/*============================================================================= Copyright (c) 2001-2003 Daniel Nuffer Copyright (c) 2001-2007 Hartmut Kaiser Revised 2007, Copyright (c) Tobias Schwinger http://spirit.sourceforge.net/ Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef BOOST_SPIRIT_TREE_COMMON_HPP #define BOOST_SPIRIT_TREE_COMMON_HPP #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) #include <vector> #else #include <list> #endif #if defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES) #include <boost/pool/pool_alloc.hpp> #endif #include <algorithm> #include <boost/ref.hpp> #include <boost/call_traits.hpp> #include <boost/spirit/home/classic/namespace.hpp> #include <boost/spirit/home/classic/core.hpp> #include <boost/assert.hpp> #if defined(BOOST_SPIRIT_DEBUG) && \ (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) #include <iostream> #include <boost/spirit/home/classic/debug/debug_node.hpp> #endif #include <boost/spirit/home/classic/tree/common_fwd.hpp> #include <iterator> // for std::iterator_traits, std::distance namespace boost { namespace spirit { BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN template <typename T> void swap(tree_node<T>& a, tree_node<T>& b); template <typename T, typename V> void swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b); namespace impl { template <typename T> inline void cp_swap(T& t1, T& t2); } template <typename T> struct tree_node { typedef T parse_node_t; #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES) typedef std::allocator<tree_node<T> > allocator_type; #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) typedef boost::pool_allocator<tree_node<T> > allocator_type; #else typedef boost::fast_pool_allocator<tree_node<T> > allocator_type; #endif #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) typedef std::vector<tree_node<T>, allocator_type> children_t; #else typedef std::list<tree_node<T>, allocator_type> children_t; #endif // BOOST_SPIRIT_USE_LIST_FOR_TREES typedef typename children_t::iterator tree_iterator; typedef typename children_t::const_iterator const_tree_iterator; T value; children_t children; tree_node() : value() , children() {} explicit tree_node(T const& v) : value(v) , children() {} tree_node(T const& v, children_t const& c) : value(v) , children(c) {} void swap(tree_node<T>& x) { impl::cp_swap(value, x.value); impl::cp_swap(children, x.children); } // Intel V5.0.1 has a problem without this explicit operator= tree_node &operator= (tree_node const &rhs) { tree_node(rhs).swap(*this); return *this; } }; #if defined(BOOST_SPIRIT_DEBUG) && \ (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) template <typename T> inline std::ostream& operator<<(std::ostream& o, tree_node<T> const& n) { static int depth = 0; o << "\n"; for (int i = 0; i <= depth; ++i) { o << "\t"; } o << "(depth = " << depth++ << " value = " << n.value; int c = 0; for (typename tree_node<T>::children_t::const_iterator it = n.children.begin(); it != n.children.end(); ++it) { o << " children[" << c++ << "] = " << *it; } o << ")"; --depth; return o; } #endif ////////////////////////////////// template <typename IteratorT, typename ValueT> struct node_iter_data { typedef IteratorT iterator_t; typedef IteratorT /*const*/ const_iterator_t; node_iter_data() : first(), last(), is_root_(false), parser_id_(), value_() {} node_iter_data(IteratorT const& _first, IteratorT const& _last) : first(_first), last(_last), is_root_(false), parser_id_(), value_() {} void swap(node_iter_data& x) { impl::cp_swap(first, x.first); impl::cp_swap(last, x.last); impl::cp_swap(parser_id_, x.parser_id_); impl::cp_swap(is_root_, x.is_root_); impl::cp_swap(value_, x.value_); } IteratorT begin() { return first; } IteratorT const& begin() const { return first; } IteratorT end() { return last; } IteratorT const& end() const { return last; } bool is_root() const { return is_root_; } void is_root(bool b) { is_root_ = b; } parser_id id() const { return parser_id_; } void id(parser_id r) { parser_id_ = r; } ValueT const& value() const { return value_; } void value(ValueT const& v) { value_ = v; } private: IteratorT first, last; bool is_root_; parser_id parser_id_; ValueT value_; public: }; #if defined(BOOST_SPIRIT_DEBUG) && \ (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) // value is default nil_t, so provide an operator<< for nil_t inline std::ostream& operator<<(std::ostream& o, nil_t const&) { return o; } template <typename IteratorT, typename ValueT> inline std::ostream& operator<<(std::ostream& o, node_iter_data<IteratorT, ValueT> const& n) { o << "(id = " << n.id() << " text = \""; typedef typename node_iter_data<IteratorT, ValueT>::const_iterator_t iterator_t; for (iterator_t it = n.begin(); it != n.end(); ++it) impl::token_printer(o, *it); o << "\" is_root = " << n.is_root() << /*" value = " << n.value() << */")"; return o; } #endif ////////////////////////////////// template <typename IteratorT = char const*, typename ValueT = nil_t> struct node_val_data { typedef typename std::iterator_traits<IteratorT>::value_type value_type; #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES) typedef std::allocator<value_type> allocator_type; #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) typedef boost::pool_allocator<value_type> allocator_type; #else typedef boost::fast_pool_allocator<value_type> allocator_type; #endif #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) typedef std::vector<value_type, allocator_type> container_t; #else typedef std::list<value_type, allocator_type> container_t; #endif typedef typename container_t::iterator iterator_t; typedef typename container_t::const_iterator const_iterator_t; node_val_data() : text(), is_root_(false), parser_id_(), value_() {} #if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) node_val_data(IteratorT const& _first, IteratorT const& _last) : text(), is_root_(false), parser_id_(), value_() { std::copy(_first, _last, std::inserter(text, text.end())); } // This constructor is for building text out of iterators template <typename IteratorT2> node_val_data(IteratorT2 const& _first, IteratorT2 const& _last) : text(), is_root_(false), parser_id_(), value_() { std::copy(_first, _last, std::inserter(text, text.end())); } #else node_val_data(IteratorT const& _first, IteratorT const& _last) : text(_first, _last), is_root_(false), parser_id_(), value_() {} // This constructor is for building text out of iterators template <typename IteratorT2> node_val_data(IteratorT2 const& _first, IteratorT2 const& _last) : text(_first, _last), is_root_(false), parser_id_(), value_() {} #endif void swap(node_val_data& x) { impl::cp_swap(text, x.text); impl::cp_swap(is_root_, x.is_root_); impl::cp_swap(parser_id_, x.parser_id_); impl::cp_swap(value_, x.value_); } typename container_t::iterator begin() { return text.begin(); } typename container_t::const_iterator begin() const { return text.begin(); } typename container_t::iterator end() { return text.end(); } typename container_t::const_iterator end() const { return text.end(); } bool is_root() const { return is_root_; } void is_root(bool b) { is_root_ = b; } parser_id id() const { return parser_id_; } void id(parser_id r) { parser_id_ = r; } ValueT const& value() const { return value_; } void value(ValueT const& v) { value_ = v; } private: container_t text; bool is_root_; parser_id parser_id_; ValueT value_; }; #if defined(BOOST_SPIRIT_DEBUG) && \ (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) template <typename IteratorT, typename ValueT> inline std::ostream& operator<<(std::ostream& o, node_val_data<IteratorT, ValueT> const& n) { o << "(id = " << n.id() << " text = \""; typedef typename node_val_data<IteratorT, ValueT>::const_iterator_t iterator_t; for (iterator_t it = n.begin(); it != n.end(); ++it) impl::token_printer(o, *it); o << "\" is_root = " << n.is_root() << " value = " << n.value() << ")"; return o; } #endif template <typename T> inline void swap(tree_node<T>& a, tree_node<T>& b) { a.swap(b); } template <typename T, typename V> inline void swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b) { a.swap(b); } ////////////////////////////////// template <typename ValueT> class node_iter_data_factory { public: // This inner class is so that node_iter_data_factory can simulate // a template template parameter template <typename IteratorT> class factory { public: typedef IteratorT iterator_t; typedef node_iter_data<iterator_t, ValueT> node_t; static node_t create_node(iterator_t const& first, iterator_t const& last, bool /*is_leaf_node*/) { return node_t(first, last); } static node_t empty_node() { return node_t(); } // precondition: ContainerT contains a tree_node<node_t>. And all // iterators in the container point to the same sequence. template <typename ContainerT> static node_t group_nodes(ContainerT const& nodes) { return node_t(nodes.begin()->value.begin(), nodes.back().value.end()); } }; }; ////////////////////////////////// template <typename ValueT> class node_val_data_factory { public: // This inner class is so that node_val_data_factory can simulate // a template template parameter template <typename IteratorT> class factory { public: typedef IteratorT iterator_t; typedef node_val_data<iterator_t, ValueT> node_t; static node_t create_node(iterator_t const& first, iterator_t const& last, bool is_leaf_node) { if (is_leaf_node) return node_t(first, last); else return node_t(); } static node_t empty_node() { return node_t(); } template <typename ContainerT> static node_t group_nodes(ContainerT const& nodes) { typename node_t::container_t c; typename ContainerT::const_iterator i_end = nodes.end(); // copy all the nodes text into a new one for (typename ContainerT::const_iterator i = nodes.begin(); i != i_end; ++i) { // See docs: reduced_node_d cannot be used with a // rule inside the []. BOOST_ASSERT(i->children.size() == 0); c.insert(c.end(), i->value.begin(), i->value.end()); } return node_t(c.begin(), c.end()); } }; }; ////////////////////////////////// template <typename ValueT> class node_all_val_data_factory { public: // This inner class is so that node_all_val_data_factory can simulate // a template template parameter template <typename IteratorT> class factory { public: typedef IteratorT iterator_t; typedef node_val_data<iterator_t, ValueT> node_t; static node_t create_node(iterator_t const& first, iterator_t const& last, bool /*is_leaf_node*/) { return node_t(first, last); } static node_t empty_node() { return node_t(); } template <typename ContainerT> static node_t group_nodes(ContainerT const& nodes) { typename node_t::container_t c; typename ContainerT::const_iterator i_end = nodes.end(); // copy all the nodes text into a new one for (typename ContainerT::const_iterator i = nodes.begin(); i != i_end; ++i) { BOOST_ASSERT(i->children.size() == 0); c.insert(c.end(), i->value.begin(), i->value.end()); } return node_t(c.begin(), c.end()); } }; }; namespace impl { /////////////////////////////////////////////////////////////////////////// // can't call unqualified swap from within classname::swap // as Koenig lookup rules will find only the classname::swap // member function not the global declaration, so use cp_swap // as a forwarding function (JM): template <typename T> inline void cp_swap(T& t1, T& t2) { using std::swap; using BOOST_SPIRIT_CLASSIC_NS::swap; using boost::swap; swap(t1, t2); } } ////////////////////////////////// template <typename IteratorT, typename NodeFactoryT, typename T> class tree_match : public match<T> { public: typedef typename NodeFactoryT::template factory<IteratorT> node_factory_t; typedef typename node_factory_t::node_t parse_node_t; typedef tree_node<parse_node_t> node_t; typedef typename node_t::children_t container_t; typedef typename container_t::iterator tree_iterator; typedef typename container_t::const_iterator const_tree_iterator; typedef T attr_t; typedef typename boost::call_traits<T>::param_type param_type; typedef typename boost::call_traits<T>::reference reference; typedef typename boost::call_traits<T>::const_reference const_reference; tree_match() : match<T>(), trees() {} explicit tree_match(std::size_t length_) : match<T>(length_), trees() {} tree_match(std::size_t length_, parse_node_t const& n) : match<T>(length_), trees() { trees.push_back(node_t(n)); } tree_match(std::size_t length_, param_type val, parse_node_t const& n) : match<T>(length_, val), trees() { #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) trees.reserve(10); // this is more or less an arbitrary number... #endif trees.push_back(node_t(n)); } // attention, these constructors will change the second parameter! tree_match(std::size_t length_, container_t& c) : match<T>(length_), trees() { impl::cp_swap(trees, c); } tree_match(std::size_t length_, param_type val, container_t& c) : match<T>(length_, val), trees() { impl::cp_swap(trees, c); } template <typename T2> tree_match(match<T2> const& other) : match<T>(other), trees() {} template <typename T2, typename T3, typename T4> tree_match(tree_match<T2, T3, T4> const& other) : match<T>(other), trees() { impl::cp_swap(trees, other.trees); } template <typename T2> tree_match& operator=(match<T2> const& other) { match<T>::operator=(other); return *this; } template <typename T2, typename T3, typename T4> tree_match& operator=(tree_match<T2, T3, T4> const& other) { match<T>::operator=(other); impl::cp_swap(trees, other.trees); return *this; } tree_match(tree_match const& x) : match<T>(x), trees() { // use auto_ptr like ownership for the trees data member impl::cp_swap(trees, x.trees); } tree_match& operator=(tree_match const& x) { tree_match tmp(x); this->swap(tmp); return *this; } void swap(tree_match& x) { match<T>::swap(x); impl::cp_swap(trees, x.trees); } mutable container_t trees; }; #if defined(BOOST_SPIRIT_DEBUG) && \ (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) template <typename IteratorT, typename NodeFactoryT, typename T> inline std::ostream& operator<<(std::ostream& o, tree_match<IteratorT, NodeFactoryT, T> const& m) { typedef typename tree_match<IteratorT, NodeFactoryT, T>::container_t::iterator iterator; o << "(length = " << (int)m.length(); int c = 0; for (iterator i = m.trees.begin(); i != m.trees.end(); ++i) { o << " trees[" << c++ << "] = " << *i; } o << "\n)"; return o; } #endif ////////////////////////////////// struct tree_policy { template <typename FunctorT, typename MatchT> static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/) {} template <typename MatchT, typename Iterator1T, typename Iterator2T> static void group_match(MatchT& /*m*/, parser_id const& /*id*/, Iterator1T const& /*first*/, Iterator2T const& /*last*/) {} template <typename MatchT> static void concat(MatchT& /*a*/, MatchT const& /*b*/) {} }; ////////////////////////////////// template < typename MatchPolicyT, typename IteratorT, typename NodeFactoryT, typename TreePolicyT, typename T > struct common_tree_match_policy : public match_policy { common_tree_match_policy() { } template <typename PolicyT> common_tree_match_policy(PolicyT const & policies) : match_policy((match_policy const &)policies) { } template <typename U> struct result { typedef tree_match<IteratorT, NodeFactoryT, U> type; }; typedef tree_match<IteratorT, NodeFactoryT, T> match_t; typedef IteratorT iterator_t; typedef TreePolicyT tree_policy_t; typedef NodeFactoryT factory_t; static const match_t no_match() { return match_t(); } static const match_t empty_match() { return match_t(0, tree_policy_t::empty_node()); } template <typename AttrT, typename Iterator1T, typename Iterator2T> static tree_match<IteratorT, NodeFactoryT, AttrT> create_match( std::size_t length, AttrT const& val, Iterator1T const& first, Iterator2T const& last) { #if defined(BOOST_SPIRIT_DEBUG) && \ (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) BOOST_SPIRIT_DEBUG_OUT << "\n>>> create_node(begin) <<<\n" "creating node text: \""; for (Iterator1T it = first; it != last; ++it) impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it); BOOST_SPIRIT_DEBUG_OUT << "\"\n"; BOOST_SPIRIT_DEBUG_OUT << ">>> create_node(end) <<<\n\n"; #endif return tree_match<IteratorT, NodeFactoryT, AttrT>(length, val, tree_policy_t::create_node(length, first, last, true)); } template <typename Match1T, typename Match2T> static void concat_match(Match1T& a, Match2T const& b) { #if defined(BOOST_SPIRIT_DEBUG) && \ (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) BOOST_SPIRIT_DEBUG_OUT << "\n>>> concat_match(begin) <<<\n"; BOOST_SPIRIT_DEBUG_OUT << "tree a:\n" << a << "\n"; BOOST_SPIRIT_DEBUG_OUT << "tree b:\n" << b << "\n"; BOOST_SPIRIT_DEBUG_OUT << ">>> concat_match(end) <<<\n\n"; #endif BOOST_SPIRIT_ASSERT(a && b); if (a.length() == 0) { a = b; return; } else if (b.length() == 0 #ifdef BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING && !b.trees.begin()->value.id().to_long() #endif ) { return; } a.concat(b); tree_policy_t::concat(a, b); } template <typename MatchT, typename IteratorT2> void group_match( MatchT& m, parser_id const& id, IteratorT2 const& first, IteratorT2 const& last) const { if (!m) return; #if defined(BOOST_SPIRIT_DEBUG) && \ (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_TREES) BOOST_SPIRIT_DEBUG_OUT << "\n>>> group_match(begin) <<<\n" "new node(" << id << ") \""; for (IteratorT2 it = first; it != last; ++it) impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it); BOOST_SPIRIT_DEBUG_OUT << "\"\n"; BOOST_SPIRIT_DEBUG_OUT << "new child tree (before grouping):\n" << m << "\n"; tree_policy_t::group_match(m, id, first, last); BOOST_SPIRIT_DEBUG_OUT << "new child tree (after grouping):\n" << m << "\n"; BOOST_SPIRIT_DEBUG_OUT << ">>> group_match(end) <<<\n\n"; #else tree_policy_t::group_match(m, id, first, last); #endif } }; ////////////////////////////////// template <typename MatchPolicyT, typename NodeFactoryT> struct common_tree_tree_policy { typedef typename MatchPolicyT::iterator_t iterator_t; typedef typename MatchPolicyT::match_t match_t; typedef typename NodeFactoryT::template factory<iterator_t> factory_t; typedef typename factory_t::node_t node_t; template <typename Iterator1T, typename Iterator2T> static node_t create_node(std::size_t /*length*/, Iterator1T const& first, Iterator2T const& last, bool leaf_node) { return factory_t::create_node(first, last, leaf_node); } static node_t empty_node() { return factory_t::empty_node(); } template <typename FunctorT> static void apply_op_to_match(FunctorT const& op, match_t& m) { op(m); } }; ////////////////////////////////// // directives to modify how the parse tree is generated struct no_tree_gen_node_parser_gen; template <typename T> struct no_tree_gen_node_parser : public unary<T, parser<no_tree_gen_node_parser<T> > > { typedef no_tree_gen_node_parser<T> self_t; typedef no_tree_gen_node_parser_gen parser_generator_t; typedef unary_parser_category parser_category_t; no_tree_gen_node_parser(T const& a) : unary<T, parser<no_tree_gen_node_parser<T> > >(a) {} template <typename ScannerT> typename parser_result<self_t, ScannerT>::type parse(ScannerT const& scanner) const { typedef typename ScannerT::iteration_policy_t iteration_policy_t; typedef match_policy match_policy_t; typedef typename ScannerT::action_policy_t action_policy_t; typedef scanner_policies< iteration_policy_t, match_policy_t, action_policy_t > policies_t; return this->subject().parse(scanner.change_policies(policies_t(scanner))); } }; struct no_tree_gen_node_parser_gen { template <typename T> struct result { typedef no_tree_gen_node_parser<T> type; }; template <typename T> static no_tree_gen_node_parser<T> generate(parser<T> const& s) { return no_tree_gen_node_parser<T>(s.derived()); } template <typename T> no_tree_gen_node_parser<T> operator[](parser<T> const& s) const { return no_tree_gen_node_parser<T>(s.derived()); } }; const no_tree_gen_node_parser_gen no_node_d = no_tree_gen_node_parser_gen(); ////////////////////////////////// struct leaf_node_parser_gen; template<typename T> struct leaf_node_parser : public unary<T, parser<leaf_node_parser<T> > > { typedef leaf_node_parser<T> self_t; typedef leaf_node_parser_gen parser_generator_t; typedef unary_parser_category parser_category_t; leaf_node_parser(T const& a) : unary<T, parser<leaf_node_parser<T> > >(a) {} template <typename ScannerT> typename parser_result<self_t, ScannerT>::type parse(ScannerT const& scanner) const { typedef scanner_policies< typename ScannerT::iteration_policy_t, match_policy, typename ScannerT::action_policy_t > policies_t; typedef typename ScannerT::iterator_t iterator_t; typedef typename parser_result<self_t, ScannerT>::type result_t; typedef typename result_t::node_factory_t factory_t; iterator_t from = scanner.first; result_t hit = impl::contiguous_parser_parse<result_t>(this->subject(), scanner.change_policies(policies_t(scanner,match_policy(),scanner)), scanner); if (hit) return result_t(hit.length(), factory_t::create_node(from, scanner.first, true)); else return result_t(hit.length()); } }; struct leaf_node_parser_gen { template <typename T> struct result { typedef leaf_node_parser<T> type; }; template <typename T> static leaf_node_parser<T> generate(parser<T> const& s) { return leaf_node_parser<T>(s.derived()); } template <typename T> leaf_node_parser<T> operator[](parser<T> const& s) const { return leaf_node_parser<T>(s.derived()); } }; const leaf_node_parser_gen leaf_node_d = leaf_node_parser_gen(); const leaf_node_parser_gen token_node_d = leaf_node_parser_gen(); ////////////////////////////////// namespace impl { template <typename MatchPolicyT> struct tree_policy_selector { typedef tree_policy type; }; } // namespace impl ////////////////////////////////// template <typename NodeParserT> struct node_parser_gen; template <typename T, typename NodeParserT> struct node_parser : public unary<T, parser<node_parser<T, NodeParserT> > > { typedef node_parser<T, NodeParserT> self_t; typedef node_parser_gen<NodeParserT> parser_generator_t; typedef unary_parser_category parser_category_t; node_parser(T const& a) : unary<T, parser<node_parser<T, NodeParserT> > >(a) {} template <typename ScannerT> struct result { typedef typename parser_result<T, ScannerT>::type type; }; template <typename ScannerT> typename parser_result<self_t, ScannerT>::type parse(ScannerT const& scanner) const { typename parser_result<self_t, ScannerT>::type hit = this->subject().parse(scanner); if (hit) { impl::tree_policy_selector<typename ScannerT::match_policy_t>::type::apply_op_to_match(NodeParserT(), hit); } return hit; } }; template <typename NodeParserT> struct node_parser_gen { template <typename T> struct result { typedef node_parser<T, NodeParserT> type; }; template <typename T> static node_parser<T, NodeParserT> generate(parser<T> const& s) { return node_parser<T, NodeParserT>(s.derived()); } template <typename T> node_parser<T, NodeParserT> operator[](parser<T> const& s) const { return node_parser<T, NodeParserT>(s.derived()); } }; ////////////////////////////////// struct reduced_node_op { template <typename MatchT> void operator()(MatchT& m) const { if (m.trees.size() == 1) { m.trees.begin()->children.clear(); } else if (m.trees.size() > 1) { typedef typename MatchT::node_factory_t node_factory_t; m = MatchT(m.length(), node_factory_t::group_nodes(m.trees)); } } }; const node_parser_gen<reduced_node_op> reduced_node_d = node_parser_gen<reduced_node_op>(); struct discard_node_op { template <typename MatchT> void operator()(MatchT& m) const { m.trees.clear(); } }; const node_parser_gen<discard_node_op> discard_node_d = node_parser_gen<discard_node_op>(); struct infix_node_op { template <typename MatchT> void operator()(MatchT& m) const { typedef typename MatchT::container_t container_t; typedef typename MatchT::container_t::iterator iter_t; typedef typename MatchT::container_t::value_type value_t; using std::swap; using boost::swap; using BOOST_SPIRIT_CLASSIC_NS::swap; // copying the tree nodes is expensive, since it may copy a whole // tree. swapping them is cheap, so swap the nodes we want into // a new container of children. container_t new_children; std::size_t length = 0; std::size_t tree_size = m.trees.size(); // the infix_node_d[] make no sense for nodes with no subnodes BOOST_SPIRIT_ASSERT(tree_size >= 1); bool keep = true; #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) new_children.reserve((tree_size+1)/2); #endif iter_t i_end = m.trees.end(); for (iter_t i = m.trees.begin(); i != i_end; ++i) { if (keep) { // adjust the length length += std::distance((*i).value.begin(), (*i).value.end()); // move the child node new_children.push_back(value_t()); swap(new_children.back(), *i); keep = false; } else { // ignore this child node keep = true; } } m = MatchT(length, new_children); } }; const node_parser_gen<infix_node_op> infix_node_d = node_parser_gen<infix_node_op>(); struct discard_first_node_op { template <typename MatchT> void operator()(MatchT& m) const { typedef typename MatchT::container_t container_t; typedef typename MatchT::container_t::iterator iter_t; typedef typename MatchT::container_t::value_type value_t; using std::swap; using boost::swap; using BOOST_SPIRIT_CLASSIC_NS::swap; // copying the tree nodes is expensive, since it may copy a whole // tree. swapping them is cheap, so swap the nodes we want into // a new container of children, instead of saying // m.trees.erase(m.trees.begin()) because, on a container_t that will // cause all the nodes afterwards to be copied into the previous // position. container_t new_children; std::size_t length = 0; std::size_t tree_size = m.trees.size(); // the discard_first_node_d[] make no sense for nodes with no subnodes BOOST_SPIRIT_ASSERT(tree_size >= 1); if (tree_size > 1) { #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) new_children.reserve(tree_size - 1); #endif iter_t i = m.trees.begin(), i_end = m.trees.end(); for (++i; i != i_end; ++i) { // adjust the length length += std::distance((*i).value.begin(), (*i).value.end()); // move the child node new_children.push_back(value_t()); swap(new_children.back(), *i); } } else { // if there was a tree and now there isn't any, insert an empty node iter_t i = m.trees.begin(); // This isn't entirely correct, since the empty node will reference // the end of the discarded node, but I currently don't see any way to // get at the begin of the node following this subnode. // This should be safe anyway because the it shouldn't get dereferenced // under any circumstances. typedef typename value_t::parse_node_t::iterator_t iterator_type; iterator_type it = (*i).value.end(); new_children.push_back( value_t(typename value_t::parse_node_t(it, it))); } m = MatchT(length, new_children); } }; const node_parser_gen<discard_first_node_op> discard_first_node_d = node_parser_gen<discard_first_node_op>(); struct discard_last_node_op { template <typename MatchT> void operator()(MatchT& m) const { typedef typename MatchT::container_t container_t; typedef typename MatchT::container_t::iterator iter_t; typedef typename MatchT::container_t::value_type value_t; using std::swap; using boost::swap; using BOOST_SPIRIT_CLASSIC_NS::swap; // copying the tree nodes is expensive, since it may copy a whole // tree. swapping them is cheap, so swap the nodes we want into // a new container of children, instead of saying // m.trees.erase(m.trees.begin()) because, on a container_t that will // cause all the nodes afterwards to be copied into the previous // position. container_t new_children; std::size_t length = 0; std::size_t tree_size = m.trees.size(); // the discard_last_node_d[] make no sense for nodes with no subnodes BOOST_SPIRIT_ASSERT(tree_size >= 1); if (tree_size > 1) { m.trees.pop_back(); #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) new_children.reserve(tree_size - 1); #endif iter_t i_end = m.trees.end(); for (iter_t i = m.trees.begin(); i != i_end; ++i) { // adjust the length length += std::distance((*i).value.begin(), (*i).value.end()); // move the child node new_children.push_back(value_t()); swap(new_children.back(), *i); } } else { // if there was a tree and now there isn't any, insert an empty node iter_t i = m.trees.begin(); typedef typename value_t::parse_node_t::iterator_t iterator_type; iterator_type it = (*i).value.begin(); new_children.push_back( value_t(typename value_t::parse_node_t(it, it))); } m = MatchT(length, new_children); } }; const node_parser_gen<discard_last_node_op> discard_last_node_d = node_parser_gen<discard_last_node_op>(); struct inner_node_op { template <typename MatchT> void operator()(MatchT& m) const { typedef typename MatchT::container_t container_t; typedef typename MatchT::container_t::iterator iter_t; typedef typename MatchT::container_t::value_type value_t; using std::swap; using boost::swap; using BOOST_SPIRIT_CLASSIC_NS::swap; // copying the tree nodes is expensive, since it may copy a whole // tree. swapping them is cheap, so swap the nodes we want into // a new container of children, instead of saying // m.trees.erase(m.trees.begin()) because, on a container_t that will // cause all the nodes afterwards to be copied into the previous // position. container_t new_children; std::size_t length = 0; std::size_t tree_size = m.trees.size(); // the inner_node_d[] make no sense for nodes with less then 2 subnodes BOOST_SPIRIT_ASSERT(tree_size >= 2); if (tree_size > 2) { m.trees.pop_back(); // erase the last element #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) new_children.reserve(tree_size - 1); #endif iter_t i = m.trees.begin(); // skip over the first element iter_t i_end = m.trees.end(); for (++i; i != i_end; ++i) { // adjust the length length += std::distance((*i).value.begin(), (*i).value.end()); // move the child node new_children.push_back(value_t()); swap(new_children.back(), *i); } } else { // if there was a tree and now there isn't any, insert an empty node iter_t i = m.trees.begin(); // skip over the first element typedef typename value_t::parse_node_t::iterator_t iterator_type; iterator_type it = (*++i).value.begin(); new_children.push_back( value_t(typename value_t::parse_node_t(it, it))); } m = MatchT(length, new_children); } }; const node_parser_gen<inner_node_op> inner_node_d = node_parser_gen<inner_node_op>(); ////////////////////////////////// // action_directive_parser and action_directive_parser_gen // are meant to be used as a template to create directives that // generate action classes. For example access_match and // access_node. The ActionParserT template parameter must be // a class that has an innter class called action that is templated // on the parser type and the action type. template <typename ActionParserT> struct action_directive_parser_gen; template <typename T, typename ActionParserT> struct action_directive_parser : public unary<T, parser<action_directive_parser<T, ActionParserT> > > { typedef action_directive_parser<T, ActionParserT> self_t; typedef action_directive_parser_gen<ActionParserT> parser_generator_t; typedef unary_parser_category parser_category_t; action_directive_parser(T const& a) : unary<T, parser<action_directive_parser<T, ActionParserT> > >(a) {} template <typename ScannerT> struct result { typedef typename parser_result<T, ScannerT>::type type; }; template <typename ScannerT> typename parser_result<self_t, ScannerT>::type parse(ScannerT const& scanner) const { return this->subject().parse(scanner); } template <typename ActionT> typename ActionParserT::template action<action_directive_parser<T, ActionParserT>, ActionT> operator[](ActionT const& actor) const { typedef typename ActionParserT::template action<action_directive_parser, ActionT> action_t; return action_t(*this, actor); } }; ////////////////////////////////// template <typename ActionParserT> struct action_directive_parser_gen { template <typename T> struct result { typedef action_directive_parser<T, ActionParserT> type; }; template <typename T> static action_directive_parser<T, ActionParserT> generate(parser<T> const& s) { return action_directive_parser<T, ActionParserT>(s.derived()); } template <typename T> action_directive_parser<T, ActionParserT> operator[](parser<T> const& s) const { return action_directive_parser<T, ActionParserT>(s.derived()); } }; ////////////////////////////////// // Calls the attached action passing it the match from the parser // and the first and last iterators. // The inner template class is used to simulate template-template parameters // (declared in common_fwd.hpp). template <typename ParserT, typename ActionT> struct access_match_action::action : public unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > > { typedef action_parser_category parser_category; typedef action<ParserT, ActionT> self_t; template <typename ScannerT> struct result { typedef typename parser_result<ParserT, ScannerT>::type type; }; action( ParserT const& subject, ActionT const& actor_); template <typename ScannerT> typename parser_result<self_t, ScannerT>::type parse(ScannerT const& scanner) const; ActionT const &predicate() const; private: ActionT actor; }; ////////////////////////////////// template <typename ParserT, typename ActionT> access_match_action::action<ParserT, ActionT>::action( ParserT const& subject, ActionT const& actor_) : unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >(subject) , actor(actor_) {} ////////////////////////////////// template <typename ParserT, typename ActionT> template <typename ScannerT> typename parser_result<access_match_action::action<ParserT, ActionT>, ScannerT>::type access_match_action::action<ParserT, ActionT>:: parse(ScannerT const& scan) const { typedef typename ScannerT::iterator_t iterator_t; typedef typename parser_result<self_t, ScannerT>::type result_t; if (!scan.at_end()) { iterator_t save = scan.first; result_t hit = this->subject().parse(scan); actor(hit, save, scan.first); return hit; } return scan.no_match(); } ////////////////////////////////// template <typename ParserT, typename ActionT> ActionT const &access_match_action::action<ParserT, ActionT>::predicate() const { return actor; } ////////////////////////////////// const action_directive_parser_gen<access_match_action> access_match_d = action_directive_parser_gen<access_match_action>(); ////////////////////////////////// // Calls the attached action passing it the node from the parser // and the first and last iterators // The inner template class is used to simulate template-template parameters // (declared in common_fwd.hpp). template <typename ParserT, typename ActionT> struct access_node_action::action : public unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > > { typedef action_parser_category parser_category; typedef action<ParserT, ActionT> self_t; template <typename ScannerT> struct result { typedef typename parser_result<ParserT, ScannerT>::type type; }; action( ParserT const& subject, ActionT const& actor_); template <typename ScannerT> typename parser_result<self_t, ScannerT>::type parse(ScannerT const& scanner) const; ActionT const &predicate() const; private: ActionT actor; }; ////////////////////////////////// template <typename ParserT, typename ActionT> access_node_action::action<ParserT, ActionT>::action( ParserT const& subject, ActionT const& actor_) : unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >(subject) , actor(actor_) {} ////////////////////////////////// template <typename ParserT, typename ActionT> template <typename ScannerT> typename parser_result<access_node_action::action<ParserT, ActionT>, ScannerT>::type access_node_action::action<ParserT, ActionT>:: parse(ScannerT const& scan) const { typedef typename ScannerT::iterator_t iterator_t; typedef typename parser_result<self_t, ScannerT>::type result_t; if (!scan.at_end()) { iterator_t save = scan.first; result_t hit = this->subject().parse(scan); if (hit && hit.trees.size() > 0) actor(*hit.trees.begin(), save, scan.first); return hit; } return scan.no_match(); } ////////////////////////////////// template <typename ParserT, typename ActionT> ActionT const &access_node_action::action<ParserT, ActionT>::predicate() const { return actor; } ////////////////////////////////// const action_directive_parser_gen<access_node_action> access_node_d = action_directive_parser_gen<access_node_action>(); ////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // tree_parse_info // // Results returned by the tree parse functions: // // stop: points to the final parse position (i.e parsing // processed the input up to this point). // // match: true if parsing is successful. This may be full: // the parser consumed all the input, or partial: // the parser consumed only a portion of the input. // // full: true when we have a full match (i.e the parser // consumed all the input. // // length: The number of characters consumed by the parser. // This is valid only if we have a successful match // (either partial or full). A negative value means // that the match is unsucessful. // // trees: Contains the root node(s) of the tree. // /////////////////////////////////////////////////////////////////////////////// template < typename IteratorT, typename NodeFactoryT, typename T > struct tree_parse_info { IteratorT stop; bool match; bool full; std::size_t length; typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees; tree_parse_info() : stop() , match(false) , full(false) , length(0) , trees() {} template <typename IteratorT2> tree_parse_info(tree_parse_info<IteratorT2> const& pi) : stop(pi.stop) , match(pi.match) , full(pi.full) , length(pi.length) , trees() { using std::swap; using boost::swap; using BOOST_SPIRIT_CLASSIC_NS::swap; // use auto_ptr like ownership for the trees data member swap(trees, pi.trees); } tree_parse_info( IteratorT stop_, bool match_, bool full_, std::size_t length_, typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees_) : stop(stop_) , match(match_) , full(full_) , length(length_) , trees() { using std::swap; using boost::swap; using BOOST_SPIRIT_CLASSIC_NS::swap; // use auto_ptr like ownership for the trees data member swap(trees, trees_); } }; BOOST_SPIRIT_CLASSIC_NAMESPACE_END }} // namespace BOOST_SPIRIT_CLASSIC_NS #endif