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 + -
显示快捷键?