⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpp_iterator.hpp

📁 C++的一个好库。。。现在很流行
💻 HPP
📖 第 1 页 / 共 5 页
字号:
    // eat all T_PLACEHOLDER tokens, eventually slipped through out of the
    // macro engine
    do { 
        if (!pending_queue.empty()) {
        // if there are pending tokens in the queue, return the first one
            act_token = pending_queue.front();
            pending_queue.pop_front();
        }
        else if (!unput_queue.empty() 
            || T_IDENTIFIER == id 
            || IS_CATEGORY(id, KeywordTokenType)
            || IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType))
        {
        //  call the lexer, preprocess the required number of tokens, put them
        //  into the unput queue
            act_token = ctx.expand_tokensequence(iter_ctx->first, 
                iter_ctx->last, pending_queue, unput_queue);
        }
        else {
        // simply return the next token
            act_token = *iter_ctx->first;
            ++iter_ctx->first;
        }
        id = token_id(act_token);
        
    } while (T_PLACEHOLDER == id);

    return act_token;
}

///////////////////////////////////////////////////////////////////////////////
//
//  pp_directive(): recognize a preprocessor directive
//
///////////////////////////////////////////////////////////////////////////////
namespace {

    template <typename IteratorT>
    bool next_token_is_pp_directive(IteratorT &it, IteratorT const &end)
    {
        using namespace boost::wave;
        
        token_id id = T_ANY;
        for (/**/; it != end; ++it) {
            id = token_id(*it);
            if (!IS_CATEGORY(id, WhiteSpaceTokenType))
                break;          // skip leading whitespace
            if (IS_CATEGORY(id, EOLTokenType))
                break;          // do not enter a new line
        }
        BOOST_ASSERT(it == end || id != T_ANY);
        return it != end && IS_CATEGORY(id, PPTokenType);
    }
    
    template <typename IteratorT>
    bool is_pp_null(IteratorT &it, IteratorT const &end)
    {
        using namespace boost::wave;
        
        BOOST_ASSERT(T_POUND == BASE_TOKEN(token_id(*it)));
        for (++it; it != end; ++it) {
        token_id id = token_id(*it);
        
            if (T_CPPCOMMENT == id || T_NEWLINE == id) {
                ++it;           // skip eol/C++ comment
                return true;    // found pp_null
            }

            if (!IS_CATEGORY(id, WhiteSpaceTokenType))
                break;
        }
        return false;
    }

    template <typename IteratorT>
    bool skip_to_eol(IteratorT &it, IteratorT const &end)
    {
        using namespace boost::wave;
        
        for (/**/; it != end; ++it) {
        token_id id = token_id(*it);
        
            if (T_CPPCOMMENT == id || T_NEWLINE == id) {
                ++it;           // skip eol/C++ comment
                return true;    // found pp_null
            }
        }
        return false;
    }
}

template <typename ContextT> 
inline bool
pp_iterator_functor<ContextT>::pp_directive()
{
    using namespace cpplexer;
    
// test, if the next non-whitespace token is a pp directive
lexer_type it = iter_ctx->first;

    if (!next_token_is_pp_directive(it, iter_ctx->last)) {
    // eventually skip null pp directive (no need to do it via the parser)
        if (it != iter_ctx->last && T_POUND == BASE_TOKEN(token_id(*it))) {
            if (is_pp_null(it, iter_ctx->last)) {
                seen_newline = true;
                iter_ctx->first = it;   // start over with the next line
                return true;
            }
            else {
                on_illformed((*it).get_value());
            }
        }
        
    // this line does not contain a pp directive, so simply return
        return false;
    }
    
    if (it == iter_ctx->last)
        return false;

// ignore all pp directives not related to conditional compilation while
// if block status is false
    if (!ctx.get_if_block_status() && 
        !IS_EXTCATEGORY(*it, PPConditionalTokenType))
    {
        seen_newline = true;
        skip_to_eol(it, iter_ctx->last);
        iter_ctx->first = it;       // start over with the next line
        return true;
    }

// found a pp directive, so try to identify it, start with the pp_token
bool found_eof = false;
boost::spirit::tree_parse_info<lexer_type> hit = 
    cpp_grammar_type::parse_cpp_grammar(it, iter_ctx->last, found_eof, act_pos);

    if (hit.match) {
    // position the iterator past the matched sequence to allow 
    // resynchronisation, if an error occurs
        iter_ctx->first = hit.stop;
        
    // found a valid pp directive, dispatch to the correct function to handle 
    // the found pp directive
    bool result = dispatch_directive (hit);
    
        if (found_eof) {
        // The line was terminated with an end of file token.
        // So trigger a warning, that the last line was not terminated with a 
        // newline.
            BOOST_WAVE_THROW(preprocess_exception, last_line_not_terminated, "", 
                act_pos);
        }
        return result;
    }
    return false;
}

///////////////////////////////////////////////////////////////////////////////
//
//  dispatch_directive(): dispatch a recognized preprocessor directive
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT> 
inline bool
pp_iterator_functor<ContextT>::dispatch_directive(
    boost::spirit::tree_parse_info<lexer_type> const &hit)
{
    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 = cpp_grammar_type::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);
        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_trace_policy().found_include_directive(f, include_next);

    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 (

⌨️ 快捷键说明

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