cpp_iterator.hpp
来自「support vector clustering for vc++」· HPP 代码 · 共 1,705 行 · 第 1/5 页
HPP
1,705 行
string_type str(boost::wave::util::impl::as_string<string_type>(
iter_ctx->first, it));
iter_ctx->first = it;
// report the ill formed directive
on_illformed(str);
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
//
// dispatch_directive(): dispatch a recognized preprocessor directive
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline bool
pp_iterator_functor<ContextT>::dispatch_directive(
tree_parse_info_type const &hit, result_type const& found_directive,
token_sequence_type const& found_eoltokens)
{
using namespace cpplexer;
using namespace boost::spirit;
typedef typename parse_tree_type::const_iterator const_child_iterator_t;
// this iterator points to the root node of the parse tree
const_child_iterator_t begin = hit.trees.begin();
// decide, which preprocessor directive was found
parse_tree_type const &root = (*begin).children;
parse_node_value_type const &nodeval = get_first_leaf(*root.begin()).value;
//long node_id = nodeval.id().to_long();
const_child_iterator_t begin_child_it = (*root.begin()).children.begin();
const_child_iterator_t end_child_it = (*root.begin()).children.end();
token_id id = token_id(found_directive);
// call preprocessing hook
ctx.get_hooks().found_directive(found_directive);
switch (static_cast<unsigned int>(id)) {
case T_PP_QHEADER: // #include "..."
#if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
case T_PP_QHEADER_NEXT: // #include_next "..."
#endif
on_include ((*nodeval.begin()).get_value(), false,
T_PP_QHEADER_NEXT == id);
break;
case T_PP_HHEADER: // #include <...>
#if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
case T_PP_HHEADER_NEXT: // #include_next <...>
#endif
on_include ((*nodeval.begin()).get_value(), true,
T_PP_HHEADER_NEXT == id);
break;
case T_PP_INCLUDE: // #include ...
#if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
case T_PP_INCLUDE_NEXT: // #include_next ...
#endif
on_include (begin_child_it, end_child_it, T_PP_INCLUDE_NEXT == id);
break;
case T_PP_DEFINE: // #define
on_define (*begin);
break;
case T_PP_UNDEF: // #undef
on_undefine(*nodeval.begin());
break;
case T_PP_IFDEF: // #ifdef
on_ifdef(begin_child_it, end_child_it);
break;
case T_PP_IFNDEF: // #ifndef
on_ifndef(begin_child_it, end_child_it);
break;
case T_PP_IF: // #if
on_if(begin_child_it, end_child_it);
break;
case T_PP_ELIF: // #elif
on_elif(begin_child_it, end_child_it, found_eoltokens);
break;
case T_PP_ELSE: // #else
on_else();
break;
case T_PP_ENDIF: // #endif
on_endif();
break;
case T_PP_LINE: // #line
on_line(begin_child_it, end_child_it);
break;
case T_PP_ERROR: // #error
on_error(begin_child_it, end_child_it);
break;
#if BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0
case T_PP_WARNING: // #warning
on_warning(begin_child_it, end_child_it);
break;
#endif
case T_PP_PRAGMA: // #pragma
return on_pragma(begin_child_it, end_child_it);
#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
case T_MSEXT_PP_REGION:
case T_MSEXT_PP_ENDREGION:
break; // ignore these
#endif
default: // #something else
on_illformed((*nodeval.begin()).get_value());
break;
}
return true; // return newline only
}
///////////////////////////////////////////////////////////////////////////////
//
// on_include: handle #include <...> or #include "..." directives
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::on_include (string_type const &s,
bool is_system, bool include_next)
{
BOOST_ASSERT(ctx.get_if_block_status());
// strip quotes first, extract filename
typename string_type::size_type pos_end = s.find_last_of(is_system ? '>' : '\"');
if (string_type::npos == pos_end) {
BOOST_WAVE_THROW(preprocess_exception, bad_include_statement,
s.c_str(), act_pos);
}
typename string_type::size_type pos_begin =
s.find_last_of(is_system ? '<' : '\"', pos_end-1);
if (string_type::npos == pos_begin) {
BOOST_WAVE_THROW(preprocess_exception, bad_include_statement,
s.c_str(), act_pos);
}
std::string file_token(s.substr(pos_begin, pos_end-pos_begin+1).c_str());
std::string file_path(s.substr(pos_begin+1, pos_end-pos_begin-1).c_str());
// finally include the file
on_include_helper(file_token.c_str(), file_path.c_str(), is_system,
include_next);
}
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::on_include_helper (char const *f, char const *s,
bool is_system, bool include_next)
{
namespace fs = boost::filesystem;
// try to locate the given file, searching through the include path lists
std::string file_path(s);
std::string dir_path;
#if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
char const *current_name = include_next ? iter_ctx->real_filename.c_str() : 0;
#else
char const *current_name = 0; // never try to match current file name
#endif
// call the include policy trace function
ctx.get_hooks().found_include_directive(f, include_next);
file_path = util::impl::unescape_lit(file_path);
if (!ctx.find_include_file (file_path, dir_path, is_system, current_name)) {
BOOST_WAVE_THROW(preprocess_exception, bad_include_file,
file_path.c_str(), act_pos);
}
fs::path native_path(file_path, fs::native);
if (!fs::exists(native_path)) {
BOOST_WAVE_THROW(preprocess_exception, bad_include_file,
file_path.c_str(), act_pos);
}
// test, if this file is known through a #pragma once directive
#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
if (!ctx.has_pragma_once(native_path.native_file_string()))
#endif
{
// the new include file determines the actual current directory
ctx.set_current_directory(native_path.native_file_string().c_str());
// preprocess the opened file
boost::shared_ptr<base_iteration_context_type> new_iter_ctx (
new iteration_context_type(native_path.native_file_string().c_str(),
act_pos, boost::wave::enable_prefer_pp_numbers(ctx.get_language())));
// call the include policy trace function
ctx.get_hooks().opened_include_file(dir_path, file_path,
ctx.get_iteration_depth(), is_system);
// store current file position
iter_ctx->filename = act_pos.get_file();
iter_ctx->line = act_pos.get_line();
iter_ctx->if_block_depth = ctx.get_if_block_depth();
// push the old iteration context onto the stack and continue with the new
ctx.push_iteration_context(act_pos, iter_ctx);
iter_ctx = new_iter_ctx;
seen_newline = true; // fake a newline to trigger pp_directive
must_emit_line_directive = true;
act_pos.set_file(iter_ctx->filename); // initialize file position
#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
ctx.set_current_filename(iter_ctx->real_filename.c_str());
#endif
act_pos.set_line(iter_ctx->line);
act_pos.set_column(0);
}
}
///////////////////////////////////////////////////////////////////////////////
//
// on_include(): handle #include ... directives
//
///////////////////////////////////////////////////////////////////////////////
namespace impl {
// trim all whitespace from the beginning and the end of the given string
template <typename StringT>
inline StringT
trim_whitespace(StringT const &s)
{
typedef typename StringT::size_type size_type;
size_type first = s.find_first_not_of(" \t\v\f");
if (StringT::npos == first)
return StringT();
size_type last = s.find_last_not_of(" \t\v\f");
return s.substr(first, last-first+1);
}
}
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::on_include(
typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end, bool include_next)
{
BOOST_ASSERT(ctx.get_if_block_status());
// preprocess the given token sequence (the body of the #include directive)
get_token_value<result_type, parse_node_type> get_value;
token_sequence_type expanded;
token_sequence_type toexpand;
std::copy(make_ref_transform_iterator(begin, get_value),
make_ref_transform_iterator(end, get_value),
std::inserter(toexpand, toexpand.end()));
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
false);
// now, include the file
string_type s (impl::trim_whitespace(boost::wave::util::impl::as_string(expanded)));
bool is_system = '<' == s[0] && '>' == s[s.size()-1];
if (!is_system && !('\"' == s[0] && '\"' == s[s.size()-1])) {
// should resolve into something like <...> or "..."
BOOST_WAVE_THROW(preprocess_exception, bad_include_statement,
s.c_str(), act_pos);
}
on_include(s, is_system, include_next);
}
///////////////////////////////////////////////////////////////////////////////
//
// on_define(): handle #define directives
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::on_define (parse_node_type const &node)
{
BOOST_ASSERT(ctx.get_if_block_status());
// retrieve the macro definition from the parse tree
result_type macroname;
std::vector<result_type> macroparameters;
token_sequence_type macrodefinition;
bool has_parameters = false;
boost::wave::util::retrieve_macroname(node,
BOOST_WAVE_PLAIN_DEFINE_ID, macroname,
act_token.get_position());
has_parameters = boost::wave::util::retrieve_macrodefinition(node,
BOOST_WAVE_MACRO_PARAMETERS_ID, macroparameters, act_token);
boost::wave::util::retrieve_macrodefinition(node,
BOOST_WAVE_MACRO_DEFINITION_ID, macrodefinition, act_token);
if (has_parameters) {
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
if (boost::wave::need_variadics(ctx.get_language())) {
// test whether ellipsis are given, and if yes, if these are placed as the
// last argument, test if __VA_ARGS__ is used as a macro parameter name
using namespace cpplexer;
typedef typename std::vector<result_type>::iterator
parameter_iterator_t;
bool seen_ellipses = false;
parameter_iterator_t end = macroparameters.end();
for (parameter_iterator_t pit = macroparameters.begin();
pit != end; ++pit)
{
if (seen_ellipses) {
// ellipses are not the last given formal argument
BOOST_WAVE_THROW(preprocess_exception, bad_define_statement,
macroname.get_value().c_str(), (*pit).get_position());
}
if (T_ELLIPSIS == token_id(*pit))
seen_ellipses = true;
// can't use __VA_ARGS__ as a argument name
if ("__VA_ARGS__" == (*pit).get_value()) {
BOOST_WAVE_THROW(preprocess_exception, bad_define_statement_va_args,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?