common.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,588 行 · 第 1/3 页
HPP
1,588 行
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>::typeaccess_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>::typeaccess_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
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?