cpp_iterator.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,775 行 · 第 1/5 页

HPP
1,775
字号
/*=============================================================================    Boost.Wave: A Standard compliant C++ preprocessor library    Definition of the preprocessor iterator        http://www.boost.org/    Copyright (c) 2001-2008 Hartmut Kaiser. Distributed under the Boost    Software License, Version 1.0. (See accompanying file    LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)=============================================================================*/#if !defined(CPP_ITERATOR_HPP_175CA88F_7273_43FA_9039_BCF7459E1F29_INCLUDED)#define CPP_ITERATOR_HPP_175CA88F_7273_43FA_9039_BCF7459E1F29_INCLUDED#include <string>#include <vector>#include <list>#include <cstdlib>#include <cctype>#include <boost/assert.hpp>#include <boost/shared_ptr.hpp>#include <boost/filesystem/path.hpp>#include <boost/filesystem/operations.hpp>#include <boost/spirit/include/classic_multi_pass.hpp>#include <boost/spirit/include/classic_parse_tree_utils.hpp>#include <boost/wave/wave_config.hpp>#include <boost/pool/pool_alloc.hpp>#include <boost/wave/util/insert_whitespace_detection.hpp>#include <boost/wave/util/macro_helpers.hpp>#include <boost/wave/util/cpp_macromap_utils.hpp>#include <boost/wave/util/interpret_pragma.hpp>#include <boost/wave/util/transform_iterator.hpp>#include <boost/wave/util/functor_input.hpp>#include <boost/wave/grammars/cpp_grammar_gen.hpp>#include <boost/wave/grammars/cpp_expression_grammar_gen.hpp>#if BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0#include <boost/wave/grammars/cpp_predef_macros_gen.hpp>#endif#include <boost/wave/whitespace_handling.hpp>#include <boost/wave/cpp_iteration_context.hpp>#include <boost/wave/cpp_exceptions.hpp>#include <boost/wave/language_support.hpp>// this must occur after all of the includes and before any code appears#ifdef BOOST_HAS_ABI_HEADERS#include BOOST_ABI_PREFIX#endif///////////////////////////////////////////////////////////////////////////////namespace boost {namespace wave {namespace util {///////////////////////////////////////////////////////////////////////////////// retrieve the macro name from the parse treetemplate <    typename ContextT, typename ParseNodeT, typename TokenT,     typename PositionT>inline bool  retrieve_macroname(ContextT& ctx, ParseNodeT const &node,     boost::spirit::classic::parser_id id, TokenT &macroname, PositionT& act_pos,    bool update_position){ParseNodeT const *name_node = 0;    using boost::spirit::classic::find_node;    if (!find_node(node, id, &name_node))     {        // ill formed define statement (unexpected, should not happen)        BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_define_statement,             "bad parse tree (unexpected)", act_pos);        return false;    }    typename ParseNodeT::children_t const &children = name_node->children;    if (0 == children.size() ||         children.front().value.begin() == children.front().value.end())     {        // ill formed define statement (unexpected, should not happen)        BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_define_statement,             "bad parse tree (unexpected)", act_pos);        return false;    }// retrieve the macro name    macroname = *children.front().value.begin();    if (update_position) {        macroname.set_position(act_pos);        act_pos.set_column(act_pos.get_column() + macroname.get_value().size());    }    return true;}///////////////////////////////////////////////////////////////////////////////// retrieve the macro parameters or the macro definition from the parse treetemplate <typename ParseNodeT, typename ContainerT, typename PositionT>inline bool  retrieve_macrodefinition(    ParseNodeT const &node, boost::spirit::classic::parser_id id,     ContainerT &macrodefinition, PositionT& act_pos, bool update_position){    using namespace boost::wave;    typedef typename ParseNodeT::const_tree_iterator const_tree_iterator;// find macro parameters/macro definition inside the parse treestd::pair<const_tree_iterator, const_tree_iterator> nodes;    using boost::spirit::classic::get_node_range;    if (get_node_range(node, id, nodes)) {    // copy all parameters to the supplied container        typename ContainerT::iterator last_nonwhite = macrodefinition.end();        const_tree_iterator end = nodes.second;                for (const_tree_iterator cit = nodes.first; cit != end; ++cit) {            if ((*cit).value.begin() != (*cit).value.end()) {            typename ContainerT::iterator inserted = macrodefinition.insert(                macrodefinition.end(), *(*cit).value.begin());                                if (!IS_CATEGORY(macrodefinition.back(), WhiteSpaceTokenType) &&                    T_NEWLINE != token_id(macrodefinition.back()) &&                    T_EOF != token_id(macrodefinition.back()))                {                    last_nonwhite = inserted;                }                                if (update_position) {                    (*inserted).set_position(act_pos);                    act_pos.set_column(                        act_pos.get_column() + (*inserted).get_value().size());                }            }        }            // trim trailing whitespace (leading whitespace is trimmed by the grammar)        if (last_nonwhite != macrodefinition.end()) {            if (update_position) {                act_pos.set_column((*last_nonwhite).get_position().get_column() +                    (*last_nonwhite).get_value().size());            }            macrodefinition.erase(++last_nonwhite, macrodefinition.end());        }        return true;    }    return false;}#if BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0/////////////////////////////////////////////////////////////////////////////////  add an additional predefined macro given by a string (MACRO(x)=definition)template <typename ContextT>bool add_macro_definition(ContextT &ctx, std::string macrostring,    bool is_predefined, boost::wave::language_support language){    typedef typename ContextT::token_type token_type;    typedef typename ContextT::lexer_type lexer_type;    typedef typename token_type::position_type position_type;    typedef boost::wave::grammars::predefined_macros_grammar_gen<lexer_type>         predef_macros_type;    using namespace boost::wave;    using namespace std;    // isspace is in std namespace for some systems    // skip leading whitespacestd::string::iterator begin = macrostring.begin();std::string::iterator end = macrostring.end();    while(begin != end && isspace(*begin))        ++begin;        // parse the macro definitionposition_type act_pos("<command line>");boost::spirit::classic::tree_parse_info<lexer_type> hit =     predef_macros_type::parse_predefined_macro(        lexer_type(begin, end, position_type(), language), lexer_type());    if (!hit.match || (!hit.full && T_EOF != token_id(*hit.stop))) {        BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_macro_definition,             macrostring.c_str(), act_pos);        return false;    }// retrieve the macro definition from the parse treetoken_type macroname;std::vector<token_type> macroparameters;typename ContextT::token_sequence_type macrodefinition;bool has_parameters = false;    if (!boost::wave::util::retrieve_macroname(ctx, *hit.trees.begin(),             BOOST_WAVE_PLAIN_DEFINE_ID, macroname, act_pos, true))        return false;    has_parameters = boost::wave::util::retrieve_macrodefinition(*hit.trees.begin(),         BOOST_WAVE_MACRO_PARAMETERS_ID, macroparameters, act_pos, true);    boost::wave::util::retrieve_macrodefinition(*hit.trees.begin(),         BOOST_WAVE_MACRO_DEFINITION_ID, macrodefinition, act_pos, true);//  If no macrodefinition is given, and the macro string does not end with a //  '=', then the macro should be defined with the value '1'    if (0 == macrodefinition.size() &&         '=' != macrostring[macrostring.size()-1])    {        macrodefinition.push_back(token_type(T_INTLIT, "1", act_pos));    }    // add the new macro to the macromap    return ctx.add_macro_definition(macroname, has_parameters, macroparameters,         macrodefinition, is_predefined);}#endif // BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0///////////////////////////////////////////////////////////////////////////////}   // namespace util/////////////////////////////////////////////////////////////////////////////////  forward declarationtemplate <typename ContextT> class pp_iterator;namespace impl {/////////////////////////////////////////////////////////////////////////////////  //  pp_iterator_functor/////////////////////////////////////////////////////////////////////////////////template <typename ContextT> class pp_iterator_functor {public:// interface to the boost::spirit::classic::multi_pass_policies::functor_input policy    typedef typename ContextT::token_type               result_type;//  eof token    static result_type const eof;private:// type of a token sequence    typedef typename ContextT::token_sequence_type      token_sequence_type;    typedef typename ContextT::lexer_type               lexer_type;    typedef typename result_type::string_type           string_type;    typedef typename result_type::position_type         position_type;    typedef boost::wave::grammars::cpp_grammar_gen<lexer_type, token_sequence_type>         cpp_grammar_type;//  iteration context related types (an iteration context represents a current//  position in an included file)    typedef base_iteration_context<ContextT, lexer_type>        base_iteration_context_type;    typedef iteration_context<ContextT, lexer_type> iteration_context_type;// parse tree related types    typedef typename cpp_grammar_type::node_factory_type node_factory_type;    typedef boost::spirit::classic::tree_parse_info<lexer_type, node_factory_type>         tree_parse_info_type;    typedef boost::spirit::classic::tree_match<lexer_type, node_factory_type>         parse_tree_match_type;    typedef typename parse_tree_match_type::node_t       parse_node_type;       // tree_node<node_val_data<> >    typedef typename parse_tree_match_type::parse_node_t parse_node_value_type; // node_val_data<>    typedef typename parse_tree_match_type::container_t  parse_tree_type;       // parse_node_type::children_tpublic:    template <typename IteratorT>    pp_iterator_functor(ContextT &ctx_, IteratorT const &first_,             IteratorT const &last_, typename ContextT::position_type const &pos_)    :   ctx(ctx_),         iter_ctx(new base_iteration_context_type(ctx,                lexer_type(first_, last_, pos_,                     boost::wave::enable_prefer_pp_numbers(ctx.get_language())),                 lexer_type(),                 pos_.get_file().c_str()            )),         seen_newline(true), must_emit_line_directive(false),        act_pos(ctx_.get_main_pos()),        whitespace(boost::wave::need_insert_whitespace(ctx.get_language()))    {        act_pos.set_file(pos_.get_file());#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0        ctx_.set_current_filename(pos_.get_file().c_str());#endif    }    // get the next preprocessed token    result_type const &operator()();// get the last recognized token (for error processing etc.)    result_type const &current_token() const { return act_token; }protected:    friend class pp_iterator<ContextT>;    bool on_include_helper(char const *t, char const *s, bool is_system,         bool include_next);    protected:    result_type const &get_next_token();    result_type const &pp_token();    template <typename IteratorT>    bool extract_identifier(IteratorT &it);    template <typename IteratorT>    bool ensure_is_last_on_line(IteratorT& it);    template <typename IteratorT>    bool skip_to_eol_with_check(IteratorT &it);    bool pp_directive();    template <typename IteratorT>    bool handle_pp_directive(IteratorT &it);    bool dispatch_directive(tree_parse_info_type const &hit,        result_type const& found_directive,        token_sequence_type const& found_eoltokens);    void replace_undefined_identifiers(token_sequence_type &expanded);    void on_include(string_type const &s, bool is_system, bool include_next);    void on_include(typename parse_tree_type::const_iterator const &begin,        typename parse_tree_type::const_iterator const &end, bool include_next);    void on_define(parse_node_type const &node);    void on_undefine(lexer_type const &it);        void on_ifdef(result_type const& found_directive, lexer_type const &it);//         typename parse_tree_type::const_iterator const &end);    void on_ifndef(result_type const& found_directive, lexer_type const& it);//         typename parse_tree_type::const_iterator const &end);    void on_else();    void on_endif();    void on_illformed(typename result_type::string_type s);            void on_line(typename parse_tree_type::const_iterator const &begin,        typename parse_tree_type::const_iterator const &end);    void on_if(result_type const& found_directive,        typename parse_tree_type::const_iterator const &begin,        typename parse_tree_type::const_iterator const &end);    void on_elif(result_type const& found_directive,        typename parse_tree_type::const_iterator const &begin,        typename parse_tree_type::const_iterator const &end,        token_sequence_type const& found_eoltokens);    void on_error(typename parse_tree_type::const_iterator const &begin,        typename parse_tree_type::const_iterator const &end);#if BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0    void on_warning(typename parse_tree_type::const_iterator const &begin,        typename parse_tree_type::const_iterator const &end);#endif    bool on_pragma(typename parse_tree_type::const_iterator const &begin,        typename parse_tree_type::const_iterator const &end);    bool emit_line_directive();    bool returned_from_include();    bool interpret_pragma(token_sequence_type const &pragma_body,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?