DriveHQ Start Menu
Cloud Drive Mapping
Folder Sync
Cloud Backup
True Drop Box
FTP/SFTP Hosting
Group Account
DriveHQ Start Menu
Online File Server
My Storage
|
Manage Shares
|
Publishes
|
Drop Boxes
|
Group Account
WebDAV Drive Mapping
Cloud Drive Home
|
WebDAV Guide
|
Drive Mapping Tool
|
Drive Mapping URL
Complete Data Backup
Backup Guide
|
Online Backup Tool
|
Cloud-to-Cloud Backup
FTP, Email & Web Service
FTP Home
|
FTP Hosting FAQ
|
Email Hosting
|
EmailManager
|
Web Hosting
Help & Resources
About
|
Enterprise Service
|
Partnership
|
Comparisons
|
Support
Quick Links
Security and Privacy
Download Software
Service Manual
Use Cases
Group Account
Online Help
Blog
Contact
Cloud Surveillance
Sign Up
Login
Features
Business Features
Online File Server
FTP Hosting
Cloud Drive Mapping
Cloud File Backup
Email Backup & Hosting
Cloud File Sharing
Folder Synchronization
Group Management
True Drop Box
Full-text Search
AD Integration/SSO
Mobile Access
IP Camera & DVR Solution
More...
Personal Features
Personal Cloud Drive
Backup All Devices
Mobile APPs
Personal Web Hosting
Sub-Account (for Kids)
Home/PC/Kids Monitoring
More...
Software
DriveHQ Drive Mapping Tool
DriveHQ FileManager
DriveHQ Online Backup
DriveHQ Mobile Apps
Pricing
Business Plans & Pricing
Personal Plans & Pricing
Price Comparison with Others
Feature Comparison with Others
Install Mobile App
Sign up
Creating account...
Invalid character in username! Only 0-9, a-z, A-Z, _, -, . allowed.
Username is required!
Invalid email address!
E-mail is required!
Password is required!
Password is invalid!
Password and confirmation do not match.
Confirm password is required!
I accept
Membership Agreement
Please read the Membership Agreement and check "I accept"!
Free Quick Sign-up
Sign-up Page
Log in
Signing in...
Username or e-mail address is required!
Password is required!
Keep me logged in
Quick Login
Forgot Password
Up
Upload
Download
Share
Publish
New Folder
New File
Copy
Cut
Delete
Paste
Rate
Upgrade
Rotate
Effect
Edit
Slide
History
/*============================================================================= 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