cpp_iterator.hpp
来自「support vector clustering for vc++」· HPP 代码 · 共 1,705 行 · 第 1/5 页
HPP
1,705 行
///////////////////////////////////////////////////////////////////////////////
// eof token
template <typename ContextT>
typename pp_iterator_functor<ContextT>::result_type const
pp_iterator_functor<ContextT>::eof;
///////////////////////////////////////////////////////////////////////////////
//
// returned_from_include()
//
// Tests if it is necessary to pop the include file context (eof inside
// a file was reached). If yes, it pops this context. Preprocessing will
// continue with the next outer file scope.
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline bool
pp_iterator_functor<ContextT>::returned_from_include()
{
if (iter_ctx->first == iter_ctx->last && ctx.get_iteration_depth() > 0) {
// call the include policy trace function
ctx.get_hooks().returning_from_include_file();
// restore the previous iteration context after finishing the preprocessing
// of the included file
BOOST_WAVE_STRINGTYPE oldfile = iter_ctx->real_filename;
position_type old_pos (act_pos);
// if this file has include guards handle it as if it had a #pragma once
#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
if (need_include_guard_detection(ctx.get_language())) {
std::string guard_name;
if (iter_ctx->first.has_include_guards(guard_name))
ctx.add_pragma_once_header(ctx.get_current_filename(), guard_name);
}
#endif
iter_ctx = ctx.pop_iteration_context();
must_emit_line_directive = true;
seen_newline = true;
// restore current file position
act_pos.set_file(iter_ctx->filename);
act_pos.set_line(iter_ctx->line);
act_pos.set_column(0);
// restore the actual current file and directory
#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
ctx.set_current_filename(iter_ctx->real_filename.c_str());
#endif
ctx.set_current_directory(iter_ctx->real_filename.c_str());
// ensure the integrity of the #if/#endif stack
// report unbalanced #if/#endif now to make it possible to recover properly
if (iter_ctx->if_block_depth != ctx.get_if_block_depth()) {
using boost::wave::util::impl::escape_lit;
BOOST_WAVE_THROW(preprocess_exception, unbalanced_if_endif,
escape_lit(oldfile).c_str(), old_pos);
}
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
//
// operator()(): get the next preprocessed token
//
// throws a preprocess_exception, if appropriate
//
///////////////////////////////////////////////////////////////////////////////
namespace impl {
// It may be necessary to emit a #line directive either
// - when comments need to be preserved: if the current token is not a
// whitespace, except comments
// - when comments are to be skipped: if the current token is not a
// whitespace token.
template <typename ContextT>
bool consider_emitting_line_directive(ContextT const& ctx, token_id id)
{
if (need_preserve_comments(ctx.get_language())) {
if (!IS_CATEGORY(id, EOLTokenType) && !IS_CATEGORY(id, EOFTokenType))
{
return true;
}
}
if (!IS_CATEGORY(id, WhiteSpaceTokenType) &&
!IS_CATEGORY(id, EOLTokenType) && !IS_CATEGORY(id, EOFTokenType))
{
return true;
}
return false;
}
}
template <typename ContextT>
inline typename pp_iterator_functor<ContextT>::result_type const &
pp_iterator_functor<ContextT>::operator()()
{
using namespace boost::wave;
// loop over skip able whitespace until something significant is found
bool skipped_newline = false;
bool was_seen_newline = seen_newline;
token_id id = T_UNKNOWN;
do {
// get_next_token assigns result to act_token member
if (!seen_newline && skipped_newline)
seen_newline = true;
get_next_token();
// if comments shouldn't be preserved replace them with newlines
id = token_id(act_token);
if (!need_preserve_comments(ctx.get_language()) &&
(T_CPPCOMMENT == id || context_policies::util::ccomment_has_newline(act_token)))
{
act_token.set_token_id(id = T_NEWLINE);
act_token.set_value("\n");
}
} while (ctx.get_hooks().may_skip_whitespace(ctx, act_token, skipped_newline));
// if there were skipped any newlines, we must emit a #line directive
if ((must_emit_line_directive || (was_seen_newline && skipped_newline)) &&
impl::consider_emitting_line_directive(ctx, id))
{
// must emit a #line directive
if (need_emit_line_directives(ctx.get_language()) && emit_line_directive())
{
skipped_newline = false;
ctx.get_hooks().may_skip_whitespace(ctx, act_token, skipped_newline); // feed ws eater FSM
id = token_id(act_token);
}
}
// cleanup of certain tokens required
seen_newline = false;
switch (static_cast<unsigned int>(id)) {
case T_NONREPLACABLE_IDENTIFIER:
act_token.set_token_id(T_IDENTIFIER);
id = T_IDENTIFIER;
break;
case T_GENERATEDNEWLINE: // was generated by emit_line_directive()
act_token.set_token_id(id = T_NEWLINE);
++iter_ctx->emitted_lines;
seen_newline = true;
break;
case T_NEWLINE:
case T_CPPCOMMENT:
seen_newline = true;
++iter_ctx->emitted_lines;
break;
case T_CCOMMENT: // will come here only if whitespace is preserved
iter_ctx->emitted_lines +=
context_policies::util::ccomment_count_newlines(act_token);
break;
case T_PP_NUMBER: // re-tokenize the pp-number
{
token_sequence_type rescanned;
std::string pp_number(act_token.get_value().c_str());
lexer_type it = lexer_type(pp_number.begin(),
pp_number.end(), act_token.get_position(),
ctx.get_language());
lexer_type end = lexer_type();
for (/**/; it != end && T_EOF != token_id(*it); ++it)
rescanned.push_back(*it);
pending_queue.splice(pending_queue.begin(), rescanned);
act_token = pending_queue.front();
id = token_id(act_token);
pending_queue.pop_front();
}
break;
case T_EOF:
seen_newline = true;
break;
default: // make sure whitespace at line begin keeps seen_newline status
if (IS_CATEGORY(id, WhiteSpaceTokenType))
seen_newline = skipped_newline;
break;
}
if (whitespace.must_insert(id, act_token.get_value())) {
// must insert some whitespace into the output stream to avoid adjacent
// tokens, which would form different (and wrong) tokens
whitespace.shift_tokens(T_SPACE);
pending_queue.push_front(act_token); // push this token back
return act_token = result_type(T_SPACE,
typename result_type::string_type(" "),
act_token.get_position());
}
whitespace.shift_tokens(id);
return act_token;
}
template <typename ContextT>
inline typename pp_iterator_functor<ContextT>::result_type const &
pp_iterator_functor<ContextT>::get_next_token()
{
using namespace boost::wave;
// if there is something in the unput_queue, then return the next token from
// there (all tokens in the queue are preprocessed already)
if (!pending_queue.empty() || !unput_queue.empty())
return pp_token(); // return next token
// test for EOF, if there is a pending input context, pop it back and continue
// parsing with it
bool returned_from_include_file = returned_from_include();
// try to generate the next token
if (iter_ctx->first != iter_ctx->last) {
do {
// If there are pending tokens in the queue, we'll have to return
// these. This may happen from a #pragma directive, which got replaced
// by some token sequence.
if (!pending_queue.empty()) {
util::on_exit::pop_front<token_sequence_type>
pop_front_token(pending_queue);
whitespace.shift_tokens(act_token = pending_queue.front());
return act_token;
}
// fetch the current token
act_token = *iter_ctx->first;
// adjust the current position (line and column)
bool was_seen_newline = seen_newline || returned_from_include_file;
act_pos = act_token.get_position();
// act accordingly on the current token
token_id id = token_id(act_token);
if (T_EOF == id) {
// returned from an include file, continue with the next token
whitespace.shift_tokens(T_EOF);
++iter_ctx->first;
// now make sure this line has a newline
if ((!seen_newline || act_pos.get_column() > 1) &&
!(support_option_single_line & get_support_options(ctx.get_language())))
{
// warn, if this file does not end with a newline
BOOST_WAVE_THROW(preprocess_exception,
last_line_not_terminated, "", act_pos);
}
continue; // if this is the main file, the while loop breaks
}
else if (T_NEWLINE == id || T_CPPCOMMENT == id) {
// a newline is to be returned ASAP, a C++ comment too
// (the C++ comment token includes the trailing newline)
seen_newline = true;
++iter_ctx->first;
whitespace.shift_tokens(id); // whitespace controller
if (!ctx.get_if_block_status()) {
// skip this token because of the disabled #if block
ctx.get_hooks().skipped_token(act_token);
continue;
}
return act_token;
}
seen_newline = false;
if (was_seen_newline && pp_directive()) {
// a pp directive was found
// seen_newline = true;
// must_emit_line_directive = true;
// loop to the next token to analyze
// simply fall through, since the iterator was already adjusted
// correctly
}
else if (ctx.get_if_block_status()) {
// preprocess this token, eat up more, if appropriate, return
// the next preprocessed token
return pp_token(was_seen_newline);
}
else {
// compilation condition is false: if the current token is a
// newline, account for it, otherwise discard the actual token and
// try the next one
if (T_NEWLINE == act_token) {
seen_newline = true;
must_emit_line_directive = true;
}
// next token
ctx.get_hooks().skipped_token(act_token);
++iter_ctx->first;
}
} while ((iter_ctx->first != iter_ctx->last) ||
(returned_from_include_file = returned_from_include()));
// overall eof reached
if (ctx.get_if_block_depth() > 0 &&
!(support_option_single_line & get_support_options(ctx.get_language())))
{
// missing endif directive(s)
BOOST_WAVE_THROW(preprocess_exception, missing_matching_endif, "",
act_pos);
}
}
else {
act_token = eof; // this is the last token
}
whitespace.shift_tokens(T_EOF); // whitespace controller
return act_token; // return eof token
}
///////////////////////////////////////////////////////////////////////////////
//
// emit_line_directive(): emits a line directive from the act_token data
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline bool
pp_iterator_functor<ContextT>::emit_line_directive()
{
using namespace boost::wave;
typename ContextT::position_type pos = act_token.get_position();
if (must_emit_line_directive ||
iter_ctx->emitted_lines != act_pos.get_line())
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?