x
Yes
No
Do you want to visit DriveHQ English website?
首页
产品服务
价格
免费试用
下载客户端
关于我们
云文件服务
|
云备份服务
|
FTP服务
|
企业邮箱服务
|
网站托管
|
客户端软件
云文件服务
云备份服务
FTP服务
企业级邮箱服务
网站托管
客户端软件
common.hpp - Hosted on DriveHQ Cloud IT Platform
返回上层目录
上传
下载
共享
发布
新建文件夹
新建文件
复制
剪切
删除
粘贴
评论
升级服务
路径: \\game3dprogramming\materials\GameFactory\GameFactoryDemo\references\boost_1_35_0\boost\spirit\tree\common.hpp
旋转
特效
属性
历史版本
/*============================================================================= Copyright (c) 2001-2003 Daniel Nuffer Copyright (c) 2001-2007 Hartmut Kaiser Revised 2007, Copyright (c) Tobias Schwinger http://spirit.sourceforge.net/ Use, modification and distribution is subject to 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
#else #include
#endif #if defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES) #include
#endif #include
#include
#include
#include
#include
// for boost::detail::iterator_traits #if defined(BOOST_SPIRIT_DEBUG) && \ (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) #include
#include
#endif #include
namespace boost { namespace spirit { template
void swap(tree_node
& a, tree_node
& b); template
void swap(node_iter_data
& a, node_iter_data
& b); namespace impl { template
inline void cp_swap(T& t1, T& t2); } template
struct tree_node { typedef T parse_node_t; #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES) typedef std::allocator
> allocator_type; #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) typedef boost::pool_allocator
> allocator_type; #else typedef boost::fast_pool_allocator
> allocator_type; #endif #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) typedef std::vector
, allocator_type> children_t; #else typedef std::list
, 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
& 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
inline std::ostream& operator<<(std::ostream& o, tree_node
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
::children_t::const_iterator it = n.children.begin(); it != n.children.end(); ++it) { o << " children[" << c++ << "] = " << *it; } o << ")"; --depth; return o; } #endif ////////////////////////////////// template
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
inline std::ostream& operator<<(std::ostream& o, node_iter_data
const& n) { o << "(id = " << n.id() << " text = \""; typedef typename node_iter_data
::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
struct node_val_data { typedef typename boost::detail::iterator_traits
::value_type value_type; #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES) typedef std::allocator
allocator_type; #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) typedef boost::pool_allocator
allocator_type; #else typedef boost::fast_pool_allocator
allocator_type; #endif #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) typedef std::vector
container_t; #else typedef std::list
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
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
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
inline std::ostream& operator<<(std::ostream& o, node_val_data
const& n) { o << "(id = " << n.id() << " text = \""; typedef typename node_val_data
::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
inline void swap(tree_node
& a, tree_node
& b) { a.swap(b); } template
inline void swap(node_iter_data
& a, node_iter_data
& b) { a.swap(b); } ////////////////////////////////// template
class node_iter_data_factory { public: // This inner class is so that node_iter_data_factory can simulate // a template template parameter template
class factory { public: typedef IteratorT iterator_t; typedef node_iter_data
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
. And all // iterators in the container point to the same sequence. template
static node_t group_nodes(ContainerT const& nodes) { return node_t(nodes.begin()->value.begin(), nodes.back().value.end()); } }; }; ////////////////////////////////// template
class node_val_data_factory { public: // This inner class is so that node_val_data_factory can simulate // a template template parameter template
class factory { public: typedef IteratorT iterator_t; typedef node_val_data
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
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 []. assert(i->children.size() == 0); c.insert(c.end(), i->value.begin(), i->value.end()); } return node_t(c.begin(), c.end()); } }; }; ////////////////////////////////// template
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
class factory { public: typedef IteratorT iterator_t; typedef node_val_data
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
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) { 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): #if __GNUC__ == 2 using ::std::swap; #endif template
inline void cp_swap(T& t1, T& t2) { using std::swap; using boost::spirit::swap; using boost::swap; swap(t1, t2); } } ////////////////////////////////// template
class tree_match : public match
{ public: typedef typename NodeFactoryT::template factory
node_factory_t; typedef typename node_factory_t::node_t parse_node_t; typedef tree_node
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
::param_type param_type; typedef typename boost::call_traits
::reference reference; typedef typename boost::call_traits
::const_reference const_reference; tree_match() : match
(), trees() {} explicit tree_match(std::size_t length) : match
(length), trees() {} tree_match(std::size_t length, parse_node_t const& n) : match
(length), trees() { trees.push_back(node_t(n)); } tree_match(std::size_t length, param_type val, parse_node_t const& n) : match
(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
(length), trees() { impl::cp_swap(trees, c); } tree_match(std::size_t length, param_type val, container_t& c) : match
(length, val), trees() { impl::cp_swap(trees, c); } template
tree_match(match
const& other) : match
(other), trees() {} template
tree_match(tree_match
const& other) : match
(other), trees() { impl::cp_swap(trees, other.trees); } template
tree_match& operator=(match
const& other) { match
::operator=(other); return *this; } template
tree_match& operator=(tree_match
const& other) { match
::operator=(other); impl::cp_swap(trees, other.trees); return *this; } tree_match(tree_match const& x) : match
(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
::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
inline std::ostream& operator<<(std::ostream& o, tree_match
const& m) { typedef typename tree_match
::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
static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/) {} template
static void group_match(MatchT& /*m*/, parser_id const& /*id*/, Iterator1T const& /*first*/, Iterator2T const& /*last*/) {} template
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
common_tree_match_policy(PolicyT const & policies) : match_policy((match_policy const &)policies) { } template
struct result { typedef tree_match
type; }; typedef tree_match
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
static tree_match
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
(length, val, tree_policy_t::create_node(length, first, last, true)); } template
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
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
struct common_tree_tree_policy { typedef typename MatchPolicyT::iterator_t iterator_t; typedef typename MatchPolicyT::match_t match_t; typedef typename NodeFactoryT::template factory
factory_t; typedef typename factory_t::node_t node_t; template
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
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
struct no_tree_gen_node_parser : public unary
> > { typedef no_tree_gen_node_parser
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
> >(a) {} template
typename parser_result
::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
struct result { typedef no_tree_gen_node_parser
type; }; template
static no_tree_gen_node_parser
generate(parser
const& s) { return no_tree_gen_node_parser
(s.derived()); } template
no_tree_gen_node_parser
operator[](parser
const& s) const { return no_tree_gen_node_parser
(s.derived()); } }; const no_tree_gen_node_parser_gen no_node_d = no_tree_gen_node_parser_gen(); ////////////////////////////////// struct leaf_node_parser_gen; template
struct leaf_node_parser : public unary
> > { typedef leaf_node_parser
self_t; typedef leaf_node_parser_gen parser_generator_t; typedef unary_parser_category parser_category_t; leaf_node_parser(T const& a) : unary
> >(a) {} template
typename parser_result
::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
::type result_t; typedef typename result_t::node_factory_t factory_t; iterator_t from = scanner.first; result_t hit = impl::contiguous_parser_parse
(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
struct result { typedef leaf_node_parser
type; }; template
static leaf_node_parser
generate(parser
const& s) { return leaf_node_parser
(s.derived()); } template
leaf_node_parser
operator[](parser
const& s) const { return leaf_node_parser
(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
struct tree_policy_selector { typedef tree_policy type; }; } // namespace impl ////////////////////////////////// template
struct node_parser_gen; template
struct node_parser : public unary
> > { typedef node_parser
self_t; typedef node_parser_gen
parser_generator_t; typedef unary_parser_category parser_category_t; node_parser(T const& a) : unary
> >(a) {} template
struct result { typedef typename parser_result
::type type; }; template
typename parser_result
::type parse(ScannerT const& scanner) const { typename parser_result
::type hit = this->subject().parse(scanner); if (hit) { impl::tree_policy_selector
::type::apply_op_to_match(NodeParserT(), hit); } return hit; } }; template
struct node_parser_gen { template
struct result { typedef node_parser
type; }; template
static node_parser
generate(parser
const& s) { return node_parser
(s.derived()); } template
node_parser
operator[](parser
const& s) const { return node_parser
(s.derived()); } }; ////////////////////////////////// struct reduced_node_op { template
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_d = node_parser_gen
(); struct discard_node_op { template
void operator()(MatchT& m) const { m.trees.clear(); } }; const node_parser_gen
discard_node_d = node_parser_gen
(); struct infix_node_op { template
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::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_d = node_parser_gen
(); struct discard_first_node_op { template
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::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_d = node_parser_gen
(); struct discard_last_node_op { template
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::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_d = node_parser_gen
(); struct inner_node_op { template
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::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_d = node_parser_gen
(); ////////////////////////////////// // 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
struct action_directive_parser_gen; template
struct action_directive_parser : public unary
> > { typedef action_directive_parser
self_t; typedef action_directive_parser_gen
parser_generator_t; typedef unary_parser_category parser_category_t; action_directive_parser(T const& a) : unary
> >(a) {} template
struct result { typedef typename parser_result
::type type; }; template
typename parser_result
::type parse(ScannerT const& scanner) const { return this->subject().parse(scanner); } template
typename ActionParserT::template action
, ActionT> operator[](ActionT const& actor) const { typedef typename ActionParserT::template action
action_t; return action_t(*this, actor); } }; ////////////////////////////////// template
struct action_directive_parser_gen { template
struct result { typedef action_directive_parser
type; }; template
static action_directive_parser
generate(parser
const& s) { return action_directive_parser
(s.derived()); } template
action_directive_parser
operator[](parser
const& s) const { return action_directive_parser
(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
struct access_match_action::action : public unary
> > { typedef action_parser_category parser_category; typedef action
self_t; template
struct result { typedef typename parser_result
::type type; }; action( ParserT const& subject, ActionT const& actor_); template
typename parser_result
::type parse(ScannerT const& scanner) const; ActionT const &predicate() const; private: ActionT actor; }; ////////////////////////////////// template
access_match_action::action
::action( ParserT const& subject, ActionT const& actor_) : unary
> >(subject) , actor(actor_) {} ////////////////////////////////// template
template
typename parser_result
, ScannerT>::type access_match_action::action
:: parse(ScannerT const& scan) const { typedef typename ScannerT::iterator_t iterator_t; typedef typename parser_result
::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
ActionT const &access_match_action::action
::predicate() const { return actor; } ////////////////////////////////// const action_directive_parser_gen
access_match_d = action_directive_parser_gen
(); ////////////////////////////////// // 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
struct access_node_action::action : public unary
> > { typedef action_parser_category parser_category; typedef action
self_t; template
struct result { typedef typename parser_result
::type type; }; action( ParserT const& subject, ActionT const& actor_); template
typename parser_result
::type parse(ScannerT const& scanner) const; ActionT const &predicate() const; private: ActionT actor; }; ////////////////////////////////// template
access_node_action::action
::action( ParserT const& subject, ActionT const& actor_) : unary
> >(subject) , actor(actor_) {} ////////////////////////////////// template
template
typename parser_result
, ScannerT>::type access_node_action::action
:: parse(ScannerT const& scan) const { typedef typename ScannerT::iterator_t iterator_t; typedef typename parser_result
::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
ActionT const &access_node_action::action