📄 cpp_iterator.hpp
字号:
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
Definition of the preprocessor iterator
http://www.boost.org/
Copyright (c) 2001-2005 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/iterator/multi_pass.hpp>
#include <boost/spirit/tree/parse_tree_utils.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/wave/wave_config.hpp>
#include <boost/wave/util/insert_whitespace_detection.hpp>
#include <boost/wave/util/eat_whitespace.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/cpp_iteration_context.hpp>
#include <boost/wave/cpp_exceptions.hpp>
#include <boost/wave/language_support.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace wave {
namespace util {
///////////////////////////////////////////////////////////////////////////////
// retrieve the macro name from the parse tree
template <typename ParseNodeT, typename TokenT, typename PositionT>
inline void
retrieve_macroname(ParseNodeT const &node, boost::spirit::parser_id id,
TokenT ¯oname, PositionT const &act_pos)
{
ParseNodeT const *name_node = 0;
using boost::spirit::find_node;
if (!find_node(node, id, &name_node))
{
// ill formed define statement (unexpected, should not happen)
BOOST_WAVE_THROW(preprocess_exception, bad_define_statement,
"bad parse tree (unexpected)", act_pos);
}
typename ParseNodeT::children_t const &children = name_node->children;
if (0 == children.size() ||
children[0].value.begin() == children[0].value.end())
{
// ill formed define statement (unexpected, should not happen)
BOOST_WAVE_THROW(preprocess_exception, bad_define_statement,
"bad parse tree (unexpected)", act_pos);
}
// retrieve the macro name
macroname = *children[0].value.begin();
}
///////////////////////////////////////////////////////////////////////////////
// retrieve the macro parameters or the macro definition from the parse tree
template <typename ParseNodeT, typename TokenT, typename ContainerT>
inline bool
retrieve_macrodefinition(
ParseNodeT const &node, boost::spirit::parser_id id,
ContainerT ¯odefinition, TokenT const &/*t*/)
{
using namespace boost::wave;
typedef typename ParseNodeT::const_tree_iterator const_tree_iterator;
// find macro parameters/macro definition inside the parse tree
std::pair<const_tree_iterator, const_tree_iterator> nodes;
using boost::spirit::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;
}
}
}
// trim trailing whitespace (leading whitespace is trimmed by the grammar)
if (last_nonwhite != macrodefinition.end()) {
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 whitespace
std::string::iterator begin = macrostring.begin();
std::string::iterator end = macrostring.end();
while(begin != end && isspace(*begin))
++begin;
// parse the macro definition
position_type act_pos("command line", 0);
boost::spirit::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(preprocess_exception, bad_macro_definition,
macrostring.c_str(), act_pos);
}
// retrieve the macro definition from the parse tree
token_type macroname;
std::vector<token_type> macroparameters;
typename ContextT::token_sequence_type macrodefinition;
bool has_parameters = false;
boost::wave::util::retrieve_macroname(*hit.trees.begin(),
predef_macros_type::rule_ids.plain_define_id, macroname, act_pos);
has_parameters = boost::wave::util::retrieve_macrodefinition(*hit.trees.begin(),
predef_macros_type::rule_ids.macro_parameters_id, macroparameters,
token_type());
boost::wave::util::retrieve_macrodefinition(*hit.trees.begin(),
predef_macros_type::rule_ids.macro_definition_id, macrodefinition,
token_type());
// 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 declaration
template <typename ContextT> class pp_iterator;
namespace impl {
///////////////////////////////////////////////////////////////////////////////
//
// pp_iterator_functor
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
class pp_iterator_functor {
public:
// interface to the boost::spirit::multi_pass_policies::functor_input policy
typedef typename ContextT::token_type result_type;
// eof token
static result_type const eof;
private:
typedef typename ContextT::lexer_type lexer_type;
typedef typename result_type::string_type string_type;
typedef boost::wave::grammars::cpp_grammar_gen<lexer_type>
cpp_grammar_type;
// iteration context related types (an iteration context represents a current
// position in an included file)
typedef base_iteration_context<lexer_type> base_iteration_context_type;
typedef
iteration_context<lexer_type, typename ContextT::input_policy_type>
iteration_context_type;
// parse tree related types
typedef
boost::spirit::node_val_data_factory<boost::spirit::nil_t>
node_factory_t;
typedef
boost::spirit::tree_match<lexer_type, node_factory_t>
parse_tree_match_t;
typedef typename parse_tree_match_t::node_t parse_node_type; // tree_node<node_val_data<> >
typedef typename parse_tree_match_t::parse_node_t parse_node_value_type; // node_val_data<>
typedef typename parse_tree_match_t::container_t parse_tree_type; // parse_node_type::children_t
// type of a token sequence
typedef typename ContextT::token_sequence_type token_sequence_type;
public:
template <typename IteratorT>
pp_iterator_functor(ContextT &ctx_, IteratorT const &first_,
IteratorT const &last_, typename ContextT::position_type const &pos_,
boost::wave::language_support language)
: ctx(ctx_),
iter_ctx(new base_iteration_context_type(
lexer_type(first_, last_, pos_, language), lexer_type(),
pos_.get_file().c_str()
)),
seen_newline(true), must_emit_line_directive(false),
act_pos(ctx_.get_main_pos()), //last_line(0),
eater(need_preserve_comments(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>;
void 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(bool consider_emitting_line_directive = false);
bool pp_directive();
bool dispatch_directive(boost::spirit::tree_parse_info<lexer_type> const &hit);
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(result_type const &t);
void on_ifdef(typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end);
void on_ifndef(typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end);
void on_else();
void on_endif();
void on_illformed(typename result_type::string_type const &s);
void on_line(typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end);
void on_if(typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end);
void on_elif(typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end);
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);
result_type const &emit_line_directive();
bool returned_from_include();
bool interpret_pragma(token_sequence_type const &pragma_body,
token_sequence_type &result);
private:
ContextT &ctx; // context, this iterator is associated with
boost::shared_ptr<base_iteration_context_type> iter_ctx;
bool seen_newline; // needed for recognizing begin of line
bool must_emit_line_directive; // must emit a line directive
result_type act_token; // current token
typename result_type::position_type &act_pos; // current fileposition (references the macromap)
// unsigned int last_line; // line number of the previous token
token_sequence_type unput_queue; // tokens to be preprocessed again
token_sequence_type pending_queue; // tokens already preprocessed
// detect whether to insert additional whitespace in between two adjacent
// tokens, which otherwise would form a different token type, if
// retokenized
boost::wave::util::insert_whitespace_detection whitespace;
// remove not needed whitespace from the output stream
boost::wave::util::eat_whitespace<result_type> eater;
};
///////////////////////////////////////////////////////////////////////////////
// eof token
template <typename ContextT>
typename pp_iterator_functor<ContextT>::result_type const
pp_iterator_functor<ContextT>::eof;
///////////////////////////////////////////////////////////////////////////////
//
// returned_from_include()
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -