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 ¯oname, 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 ¯odefinition, 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 ¤t_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 + -
显示快捷键?