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