cpp_iterator.hpp

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

HPP
1,775
字号
        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 skipped_newline;           // a newline has been skipped since last one    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)            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     // re-tokenized    boost::wave::util::insert_whitespace_detection whitespace; };/////////////////////////////////////////////////////////////////////////////////  eof tokentemplate <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#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0        ctx.get_hooks().returning_from_include_file();#else        ctx.get_hooks().returning_from_include_file(ctx.derived());#endif    // 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_CTX(ctx, 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;    // make sure the cwd has been initialized    ctx.init_context();        // loop over skip able whitespace until something significant is found    bool was_seen_newline = seen_newline;    token_id id = T_UNKNOWN;            try {   // catch lexer exceptions        do {        // get_next_token assigns result to act_token member            if (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.derived(), act_token, skipped_newline));    }    catch (boost::wave::cpplexer::lexing_exception const& e) {    // dispatch any lexer exceptions to the context hook function        ctx.get_hooks().throw_exception(ctx.derived(), e);        return act_token;    }        // 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.derived(), 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(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(                util::to_string<std::string>(act_token.get_value()));            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 = was_seen_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 ctx.get_hooks().generated_token(ctx.derived(), 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 itbool 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);                return act_token = pending_queue.front();            }                    // adjust the current position (line and column)        bool was_seen_newline = seen_newline || returned_from_include_file;        // fetch the current token                    act_token = *iter_ctx->first;            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) &&                     !need_single_line(ctx.get_language()))                 {                // warn, if this file does not end with a newline                    BOOST_WAVE_THROW_CTX(ctx, 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;                                if (!ctx.get_if_block_status()) {                // skip this token because of the disabled #if block                    whitespace.shift_tokens(id);  // whitespace controller#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0                    ctx.get_hooks().skipped_token(act_token);#else                    ctx.get_hooks().skipped_token(ctx.derived(), act_token);#endif                    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();            }            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 == token_id(act_token)) {                    seen_newline = true;                    must_emit_line_directive = true;                }            // next token#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0                ctx.get_hooks().skipped_token(act_token);#else                ctx.get_hooks().skipped_token(ctx.derived(), act_token);#endif                ++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 && !need_single_line(ctx.get_language()))         {        // missing endif directive(s)            BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,                 missing_matching_endif, "", act_pos);

⌨️ 快捷键说明

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