Blame boost/wave/whitespace_handling.hpp

Packit 58578d
/*=============================================================================
Packit 58578d
    Boost.Wave: A Standard compliant C++ preprocessor library
Packit 58578d
    Whitespace eater
Packit 58578d
Packit 58578d
    http://www.boost.org/
Packit 58578d
Packit 58578d
    Copyright (c) 2003 Paul Mensonides
Packit 58578d
    Copyright (c) 2001-2012 Hartmut Kaiser.
Packit 58578d
    Distributed under the Boost Software License, Version 1.0. (See accompanying
Packit 58578d
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Packit 58578d
=============================================================================*/
Packit 58578d
Packit 58578d
#if !defined(WHITESPACE_HANDLING_HPP_INCLUDED)
Packit 58578d
#define WHITESPACE_HANDLING_HPP_INCLUDED
Packit 58578d
Packit 58578d
#include <boost/wave/wave_config.hpp>
Packit 58578d
#include <boost/wave/token_ids.hpp>
Packit 58578d
#include <boost/wave/preprocessing_hooks.hpp>
Packit 58578d
#include <boost/wave/language_support.hpp>
Packit 58578d
Packit 58578d
// this must occur after all of the includes and before any code appears
Packit 58578d
#ifdef BOOST_HAS_ABI_HEADERS
Packit 58578d
#include BOOST_ABI_PREFIX
Packit 58578d
#endif
Packit 58578d
Packit 58578d
///////////////////////////////////////////////////////////////////////////////
Packit 58578d
namespace boost {
Packit 58578d
namespace wave {
Packit 58578d
namespace context_policies {
Packit 58578d
Packit 58578d
namespace util {
Packit 58578d
    ///////////////////////////////////////////////////////////////////////////
Packit 58578d
    //  This function returns true if the given C style comment contains at
Packit 58578d
    //  least one newline
Packit 58578d
    template <typename TokenT>
Packit 58578d
    bool ccomment_has_newline(TokenT const& token)
Packit 58578d
    {
Packit 58578d
        using namespace boost::wave;
Packit 58578d
Packit 58578d
        if (T_CCOMMENT == token_id(token) &&
Packit 58578d
            TokenT::string_type::npos != token.get_value().find_first_of("\n"))
Packit 58578d
        {
Packit 58578d
            return true;
Packit 58578d
        }
Packit 58578d
        return false;
Packit 58578d
    }
Packit 58578d
Packit 58578d
    ///////////////////////////////////////////////////////////////////////////
Packit 58578d
    //  This function returns the number of newlines in the given C style
Packit 58578d
    //  comment
Packit 58578d
    template <typename TokenT>
Packit 58578d
    int ccomment_count_newlines(TokenT const& token)
Packit 58578d
    {
Packit 58578d
        using namespace boost::wave;
Packit 58578d
        int newlines = 0;
Packit 58578d
        if (T_CCOMMENT == token_id(token)) {
Packit 58578d
        typename TokenT::string_type const& value = token.get_value();
Packit 58578d
        typename TokenT::string_type::size_type p = value.find_first_of("\n");
Packit 58578d
Packit 58578d
            while (TokenT::string_type::npos != p) {
Packit 58578d
                ++newlines;
Packit 58578d
                p = value.find_first_of("\n", p+1);
Packit 58578d
            }
Packit 58578d
        }
Packit 58578d
        return newlines;
Packit 58578d
    }
Packit 58578d
Packit 58578d
#if BOOST_WAVE_SUPPORT_CPP0X != 0
Packit 58578d
    ///////////////////////////////////////////////////////////////////////////
Packit 58578d
    //  This function returns the number of newlines in the given C++11 style
Packit 58578d
    //  raw string
Packit 58578d
    template <typename TokenT>
Packit 58578d
    int rawstring_count_newlines(TokenT const& token)
Packit 58578d
    {
Packit 58578d
        using namespace boost::wave;
Packit 58578d
        int newlines = 0;
Packit 58578d
        if (T_RAWSTRINGLIT == token_id(token)) {
Packit 58578d
        typename TokenT::string_type const& value = token.get_value();
Packit 58578d
        typename TokenT::string_type::size_type p = value.find_first_of("\n");
Packit 58578d
Packit 58578d
            while (TokenT::string_type::npos != p) {
Packit 58578d
                ++newlines;
Packit 58578d
                p = value.find_first_of("\n", p+1);
Packit 58578d
            }
Packit 58578d
        }
Packit 58578d
        return newlines;
Packit 58578d
    }
Packit 58578d
#endif
Packit 58578d
}
Packit 58578d
Packit 58578d
///////////////////////////////////////////////////////////////////////////////
Packit 58578d
template <typename TokenT>
Packit 58578d
class eat_whitespace
Packit 58578d
:   public default_preprocessing_hooks
Packit 58578d
{
Packit 58578d
public:
Packit 58578d
    eat_whitespace();
Packit 58578d
Packit 58578d
    template <typename ContextT>
Packit 58578d
    bool may_skip_whitespace(ContextT const& ctx, TokenT &token,
Packit 58578d
        bool &skipped_newline);
Packit 58578d
    template <typename ContextT>
Packit 58578d
    bool may_skip_whitespace(ContextT const& ctx, TokenT &token,
Packit 58578d
        bool preserve_comments_, bool preserve_bol_whitespace_,
Packit 58578d
        bool &skipped_newline);
Packit 58578d
Packit 58578d
protected:
Packit 58578d
    bool skip_cppcomment(boost::wave::token_id id)
Packit 58578d
    {
Packit 58578d
        return !preserve_comments && T_CPPCOMMENT == id;
Packit 58578d
    }
Packit 58578d
Packit 58578d
private:
Packit 58578d
    typedef bool state_t(TokenT &token, bool &skipped_newline);
Packit 58578d
    state_t eat_whitespace::* state;
Packit 58578d
    state_t general, newline, newline_2nd, whitespace, bol_whitespace;
Packit 58578d
    bool preserve_comments;
Packit 58578d
    bool preserve_bol_whitespace;
Packit 58578d
};
Packit 58578d
Packit 58578d
template <typename TokenT>
Packit 58578d
inline
Packit 58578d
eat_whitespace<TokenT>::eat_whitespace()
Packit 58578d
:   state(&eat_whitespace::newline), preserve_comments(false),
Packit 58578d
    preserve_bol_whitespace(false)
Packit 58578d
{
Packit 58578d
}
Packit 58578d
Packit 58578d
template <typename TokenT>
Packit 58578d
template <typename ContextT>
Packit 58578d
inline bool
Packit 58578d
eat_whitespace<TokenT>::may_skip_whitespace(ContextT const& ctx, TokenT &token,
Packit 58578d
    bool &skipped_newline)
Packit 58578d
{
Packit 58578d
    // re-initialize the preserve comments state
Packit 58578d
    preserve_comments = boost::wave::need_preserve_comments(ctx.get_language());
Packit 58578d
    return (this->*state)(token, skipped_newline);
Packit 58578d
}
Packit 58578d
Packit 58578d
template <typename TokenT>
Packit 58578d
template <typename ContextT>
Packit 58578d
inline bool
Packit 58578d
eat_whitespace<TokenT>::may_skip_whitespace(ContextT const& ctx, TokenT &token,
Packit 58578d
    bool preserve_comments_, bool preserve_bol_whitespace_,
Packit 58578d
    bool &skipped_newline)
Packit 58578d
{
Packit 58578d
    // re-initialize the preserve comments state
Packit 58578d
    preserve_comments = preserve_comments_;
Packit 58578d
    preserve_bol_whitespace = preserve_bol_whitespace_;
Packit 58578d
    return (this->*state)(token, skipped_newline);
Packit 58578d
}
Packit 58578d
Packit 58578d
template <typename TokenT>
Packit 58578d
inline bool
Packit 58578d
eat_whitespace<TokenT>::general(TokenT &token, bool &skipped_newline)
Packit 58578d
{
Packit 58578d
    using namespace boost::wave;
Packit 58578d
Packit 58578d
    token_id id = token_id(token);
Packit 58578d
    if (T_NEWLINE == id || T_CPPCOMMENT == id) {
Packit 58578d
        state = &eat_whitespace::newline;
Packit 58578d
    }
Packit 58578d
    else if (T_SPACE == id || T_SPACE2 == id || T_CCOMMENT == id) {
Packit 58578d
        state = &eat_whitespace::whitespace;
Packit 58578d
Packit 58578d
        if (util::ccomment_has_newline(token))
Packit 58578d
            skipped_newline = true;
Packit 58578d
Packit 58578d
        if ((!preserve_comments || T_CCOMMENT != id) &&
Packit 58578d
            token.get_value().size() > 1)
Packit 58578d
        {
Packit 58578d
            token.set_value(" ");   // replace with a single space
Packit 58578d
        }
Packit 58578d
    }
Packit 58578d
    else {
Packit 58578d
        state = &eat_whitespace::general;
Packit 58578d
    }
Packit 58578d
    return false;
Packit 58578d
}
Packit 58578d
Packit 58578d
template <typename TokenT>
Packit 58578d
inline bool
Packit 58578d
eat_whitespace<TokenT>::newline(TokenT &token, bool &skipped_newline)
Packit 58578d
{
Packit 58578d
    using namespace boost::wave;
Packit 58578d
Packit 58578d
    token_id id = token_id(token);
Packit 58578d
    if (T_NEWLINE == id || T_CPPCOMMENT == id) {
Packit 58578d
        skipped_newline = true;
Packit 58578d
        state = &eat_whitespace::newline_2nd;
Packit 58578d
        return T_NEWLINE == id || skip_cppcomment(id);
Packit 58578d
    }
Packit 58578d
Packit 58578d
    if (T_SPACE != id && T_SPACE2 != id && T_CCOMMENT != id)
Packit 58578d
        return general(token, skipped_newline);
Packit 58578d
Packit 58578d
    if (T_CCOMMENT == id) {
Packit 58578d
        if (util::ccomment_has_newline(token)) {
Packit 58578d
            skipped_newline = true;
Packit 58578d
            state = &eat_whitespace::newline_2nd;
Packit 58578d
        }
Packit 58578d
        if (preserve_comments) {
Packit 58578d
            state = &eat_whitespace::general;
Packit 58578d
            return false;
Packit 58578d
        }
Packit 58578d
        return true;
Packit 58578d
    }
Packit 58578d
Packit 58578d
    if (preserve_bol_whitespace) {
Packit 58578d
        state = &eat_whitespace::bol_whitespace;
Packit 58578d
        return false;
Packit 58578d
    }
Packit 58578d
Packit 58578d
    return true;
Packit 58578d
}
Packit 58578d
Packit 58578d
template <typename TokenT>
Packit 58578d
inline bool
Packit 58578d
eat_whitespace<TokenT>::newline_2nd(TokenT &token, bool &skipped_newline)
Packit 58578d
{
Packit 58578d
    using namespace boost::wave;
Packit 58578d
Packit 58578d
    token_id id = token_id(token);
Packit 58578d
    if (T_SPACE == id || T_SPACE2 == id) {
Packit 58578d
        if (preserve_bol_whitespace) {
Packit 58578d
            state = &eat_whitespace::bol_whitespace;
Packit 58578d
            return false;
Packit 58578d
        }
Packit 58578d
        return true;
Packit 58578d
    }
Packit 58578d
Packit 58578d
    if (T_CCOMMENT == id) {
Packit 58578d
        if (util::ccomment_has_newline(token))
Packit 58578d
            skipped_newline = true;
Packit 58578d
Packit 58578d
        if (preserve_comments) {
Packit 58578d
            state = &eat_whitespace::general;
Packit 58578d
            return false;
Packit 58578d
        }
Packit 58578d
        return  true;
Packit 58578d
    }
Packit 58578d
Packit 58578d
    if (T_NEWLINE != id && T_CPPCOMMENT != id)
Packit 58578d
        return general(token, skipped_newline);
Packit 58578d
Packit 58578d
    skipped_newline = true;
Packit 58578d
    return T_NEWLINE == id || skip_cppcomment(id);
Packit 58578d
}
Packit 58578d
Packit 58578d
template <typename TokenT>
Packit 58578d
inline bool
Packit 58578d
eat_whitespace<TokenT>::bol_whitespace(TokenT &token, bool &skipped_newline)
Packit 58578d
{
Packit 58578d
    using namespace boost::wave;
Packit 58578d
Packit 58578d
    token_id id = token_id(token);
Packit 58578d
    if (T_SPACE == id || T_SPACE2 == id)
Packit 58578d
        return !preserve_bol_whitespace;
Packit 58578d
Packit 58578d
    return general(token, skipped_newline);
Packit 58578d
}
Packit 58578d
Packit 58578d
template <typename TokenT>
Packit 58578d
inline bool
Packit 58578d
eat_whitespace<TokenT>::whitespace(TokenT &token, bool &skipped_newline)
Packit 58578d
{
Packit 58578d
    using namespace boost::wave;
Packit 58578d
Packit 58578d
    token_id id = token_id(token);
Packit 58578d
    if (T_SPACE != id && T_SPACE2 != id &&
Packit 58578d
        T_CCOMMENT != id && T_CPPCOMMENT != id)
Packit 58578d
    {
Packit 58578d
        return general(token, skipped_newline);
Packit 58578d
    }
Packit 58578d
Packit 58578d
    if (T_CCOMMENT == id) {
Packit 58578d
        if (util::ccomment_has_newline(token))
Packit 58578d
            skipped_newline = true;
Packit 58578d
        return !preserve_comments;
Packit 58578d
    }
Packit 58578d
Packit 58578d
    return T_SPACE == id || T_SPACE2 == id || skip_cppcomment(id);
Packit 58578d
}
Packit 58578d
Packit 58578d
///////////////////////////////////////////////////////////////////////////////
Packit 58578d
}   // namespace context_policies
Packit 58578d
}   // namespace wave
Packit 58578d
}   // namespace boost
Packit 58578d
Packit 58578d
// the suffix header occurs after all of the code
Packit 58578d
#ifdef BOOST_HAS_ABI_HEADERS
Packit 58578d
#include BOOST_ABI_SUFFIX
Packit 58578d
#endif
Packit 58578d
Packit 58578d
#endif // !defined(WHITESPACE_HANDLING_HPP_INCLUDED)
Packit 58578d