diff options
Diffstat (limited to 'boost/wave/util/insert_whitespace_detection.hpp')
-rw-r--r-- | boost/wave/util/insert_whitespace_detection.hpp | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/boost/wave/util/insert_whitespace_detection.hpp b/boost/wave/util/insert_whitespace_detection.hpp new file mode 100644 index 0000000000..8485e9c1d1 --- /dev/null +++ b/boost/wave/util/insert_whitespace_detection.hpp @@ -0,0 +1,518 @@ +/*============================================================================= + Boost.Wave: A Standard compliant C++ preprocessor library + + Detect the need to insert a whitespace token into the output stream + + http://www.boost.org/ + + Copyright (c) 2001-2011 Hartmut Kaiser. Distributed under the Boost + Software License, Version 1.0. (See accompanying file + LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#if !defined(INSERT_WHITESPACE_DETECTION_HPP_765EF77B_0513_4967_BDD6_6A38148C4C96_INCLUDED) +#define INSERT_WHITESPACE_DETECTION_HPP_765EF77B_0513_4967_BDD6_6A38148C4C96_INCLUDED + +#include <boost/wave/wave_config.hpp> +#include <boost/wave/token_ids.hpp> + +// this must occur after all of the includes and before any code appears +#ifdef BOOST_HAS_ABI_HEADERS +#include BOOST_ABI_PREFIX +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { +namespace wave { +namespace util { + +namespace impl { + +// T_IDENTIFIER + template <typename StringT> + inline bool + would_form_universal_char (StringT const &value) + { + if ('u' != value[0] && 'U' != value[0]) + return false; + if ('u' == value[0] && value.size() < 5) + return false; + if ('U' == value[0] && value.size() < 9) + return false; + + typename StringT::size_type pos = + value.find_first_not_of("0123456789abcdefABCDEF", 1); + + if (StringT::npos == pos || + ('u' == value[0] && pos > 5) || + ('U' == value[0] && pos > 9)) + { + return true; // would form an universal char + } + return false; + } + template <typename StringT> + inline bool + handle_identifier(boost::wave::token_id prev, + boost::wave::token_id before, StringT const &value) + { + using namespace boost::wave; + switch (static_cast<unsigned int>(prev)) { + case T_IDENTIFIER: + case T_NONREPLACABLE_IDENTIFIER: + case T_COMPL_ALT: + case T_OR_ALT: + case T_AND_ALT: + case T_NOT_ALT: + case T_XOR_ALT: + case T_ANDASSIGN_ALT: + case T_ORASSIGN_ALT: + case T_XORASSIGN_ALT: + case T_NOTEQUAL_ALT: + case T_FIXEDPOINTLIT: + return true; + + case T_FLOATLIT: + case T_INTLIT: + case T_PP_NUMBER: + return (value.size() > 1 || (value[0] != 'e' && value[0] != 'E')); + + // avoid constructing universal characters (\u1234) + case TOKEN_FROM_ID('\\', UnknownTokenType): + return would_form_universal_char(value); + } + return false; + } +// T_INTLIT + inline bool + handle_intlit(boost::wave::token_id prev, boost::wave::token_id /*before*/) + { + using namespace boost::wave; + switch (static_cast<unsigned int>(prev)) { + case T_IDENTIFIER: + case T_NONREPLACABLE_IDENTIFIER: + case T_INTLIT: + case T_FLOATLIT: + case T_FIXEDPOINTLIT: + case T_PP_NUMBER: + return true; + } + return false; + } +// T_FLOATLIT + inline bool + handle_floatlit(boost::wave::token_id prev, + boost::wave::token_id /*before*/) + { + using namespace boost::wave; + switch (static_cast<unsigned int>(prev)) { + case T_IDENTIFIER: + case T_NONREPLACABLE_IDENTIFIER: + case T_INTLIT: + case T_FLOATLIT: + case T_FIXEDPOINTLIT: + case T_PP_NUMBER: + return true; + } + return false; + } +// <% T_LEFTBRACE + inline bool + handle_alt_leftbrace(boost::wave::token_id prev, + boost::wave::token_id /*before*/) + { + using namespace boost::wave; + switch (static_cast<unsigned int>(prev)) { + case T_LESS: // <<% + case T_SHIFTLEFT: // <<<% + return true; + } + return false; + } +// <: T_LEFTBRACKET + inline bool + handle_alt_leftbracket(boost::wave::token_id prev, + boost::wave::token_id /*before*/) + { + using namespace boost::wave; + switch (static_cast<unsigned int>(prev)) { + case T_LESS: // <<: + case T_SHIFTLEFT: // <<<: + return true; + } + return false; + } +// T_FIXEDPOINTLIT + inline bool + handle_fixedpointlit(boost::wave::token_id prev, + boost::wave::token_id /*before*/) + { + using namespace boost::wave; + switch (static_cast<unsigned int>(prev)) { + case T_IDENTIFIER: + case T_NONREPLACABLE_IDENTIFIER: + case T_INTLIT: + case T_FLOATLIT: + case T_FIXEDPOINTLIT: + case T_PP_NUMBER: + return true; + } + return false; + } +// T_DOT + inline bool + handle_dot(boost::wave::token_id prev, boost::wave::token_id before) + { + using namespace boost::wave; + switch (static_cast<unsigned int>(prev)) { + case T_DOT: + if (T_DOT == before) + return true; // ... + break; + } + return false; + } +// T_QUESTION_MARK + inline bool + handle_questionmark(boost::wave::token_id prev, + boost::wave::token_id /*before*/) + { + using namespace boost::wave; + switch(static_cast<unsigned int>(prev)) { + case TOKEN_FROM_ID('\\', UnknownTokenType): // \? + case T_QUESTION_MARK: // ?? + return true; + } + return false; + } +// T_NEWLINE + inline bool + handle_newline(boost::wave::token_id prev, + boost::wave::token_id before) + { + using namespace boost::wave; + switch(static_cast<unsigned int>(prev)) { + case TOKEN_FROM_ID('\\', UnknownTokenType): // \ \n + case T_DIVIDE: + if (T_QUESTION_MARK == before) + return true; // ?/\n // may be \\n + break; + } + return false; + } + + inline bool + handle_parens(boost::wave::token_id prev) + { + switch (static_cast<unsigned int>(prev)) { + case T_LEFTPAREN: + case T_RIGHTPAREN: + case T_LEFTBRACKET: + case T_RIGHTBRACKET: + case T_LEFTBRACE: + case T_RIGHTBRACE: + case T_SEMICOLON: + case T_COMMA: + case T_COLON: + // no insertion between parens/brackets/braces and operators + return false; + + default: + break; + } + return true; + } + +} // namespace impl + +class insert_whitespace_detection +{ +public: + insert_whitespace_detection(bool insert_whitespace_ = true) + : insert_whitespace(insert_whitespace_), + prev(boost::wave::T_EOF), beforeprev(boost::wave::T_EOF) + {} + + template <typename StringT> + bool must_insert(boost::wave::token_id current, StringT const &value) + { + if (!insert_whitespace) + return false; // skip whitespace insertion alltogether + + using namespace boost::wave; + switch (static_cast<unsigned int>(current)) { + case T_NONREPLACABLE_IDENTIFIER: + case T_IDENTIFIER: + return impl::handle_identifier(prev, beforeprev, value); + case T_PP_NUMBER: + case T_INTLIT: + return impl::handle_intlit(prev, beforeprev); + case T_FLOATLIT: + return impl::handle_floatlit(prev, beforeprev); + case T_STRINGLIT: + if (TOKEN_FROM_ID('L', IdentifierTokenType) == prev) // 'L' + return true; + break; + case T_LEFTBRACE_ALT: + return impl::handle_alt_leftbrace(prev, beforeprev); + case T_LEFTBRACKET_ALT: + return impl::handle_alt_leftbracket(prev, beforeprev); + case T_FIXEDPOINTLIT: + return impl::handle_fixedpointlit(prev, beforeprev); + case T_DOT: + return impl::handle_dot(prev, beforeprev); + case T_QUESTION_MARK: + return impl::handle_questionmark(prev, beforeprev); + case T_NEWLINE: + return impl::handle_newline(prev, beforeprev); + + case T_LEFTPAREN: + case T_RIGHTPAREN: + case T_LEFTBRACKET: + case T_RIGHTBRACKET: + case T_SEMICOLON: + case T_COMMA: + case T_COLON: + switch (static_cast<unsigned int>(prev)) { + case T_LEFTPAREN: + case T_RIGHTPAREN: + case T_LEFTBRACKET: + case T_RIGHTBRACKET: + case T_LEFTBRACE: + case T_RIGHTBRACE: + return false; // no insertion between parens/brackets/braces + + default: + if (IS_CATEGORY(prev, OperatorTokenType)) + return false; + break; + } + break; + + case T_LEFTBRACE: + case T_RIGHTBRACE: + switch (static_cast<unsigned int>(prev)) { + case T_LEFTPAREN: + case T_RIGHTPAREN: + case T_LEFTBRACKET: + case T_RIGHTBRACKET: + case T_LEFTBRACE: + case T_RIGHTBRACE: + case T_SEMICOLON: + case T_COMMA: + case T_COLON: + return false; // no insertion between parens/brackets/braces + + case T_QUESTION_MARK: + if (T_QUESTION_MARK == beforeprev) + return true; + if (IS_CATEGORY(prev, OperatorTokenType)) + return false; + break; + + default: + break; + } + break; + + case T_MINUS: + case T_MINUSMINUS: + case T_MINUSASSIGN: + if (T_MINUS == prev || T_MINUSMINUS == prev) + return true; + if (!impl::handle_parens(prev)) + return false; + if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) + return true; + break; + + case T_PLUS: + case T_PLUSPLUS: + case T_PLUSASSIGN: + if (T_PLUS == prev || T_PLUSPLUS == prev) + return true; + if (!impl::handle_parens(prev)) + return false; + if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) + return true; + break; + + case T_DIVIDE: + case T_DIVIDEASSIGN: + if (T_DIVIDE == prev) + return true; + if (!impl::handle_parens(prev)) + return false; + if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) + return true; + break; + + case T_EQUAL: + case T_ASSIGN: + switch (static_cast<unsigned int>(prev)) { + case T_PLUSASSIGN: + case T_MINUSASSIGN: + case T_DIVIDEASSIGN: + case T_STARASSIGN: + case T_SHIFTRIGHTASSIGN: + case T_SHIFTLEFTASSIGN: + case T_EQUAL: + case T_NOTEQUAL: + case T_LESSEQUAL: + case T_GREATEREQUAL: + case T_LESS: + case T_GREATER: + case T_PLUS: + case T_MINUS: + case T_STAR: + case T_DIVIDE: + case T_ORASSIGN: + case T_ANDASSIGN: + case T_XORASSIGN: + case T_OR: + case T_AND: + case T_XOR: + case T_OROR: + case T_ANDAND: + return true; + + case T_QUESTION_MARK: + if (T_QUESTION_MARK == beforeprev) + return true; + break; + + default: + if (!impl::handle_parens(prev)) + return false; + break; + } + break; + + case T_GREATER: + if (T_MINUS == prev || T_GREATER == prev) + return true; // prevent -> or >> + if (!impl::handle_parens(prev)) + return false; + if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) + return true; + break; + + case T_LESS: + if (T_LESS == prev) + return true; // prevent << + // fall through + case T_CHARLIT: + case T_NOT: + case T_NOTEQUAL: + if (!impl::handle_parens(prev)) + return false; + if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) + return true; + break; + + case T_AND: + case T_ANDAND: + if (!impl::handle_parens(prev)) + return false; + if (T_AND == prev || T_ANDAND == prev) + return true; + break; + + case T_OR: + if (!impl::handle_parens(prev)) + return false; + if (T_OR == prev) + return true; + break; + + case T_XOR: + if (!impl::handle_parens(prev)) + return false; + if (T_XOR == prev) + return true; + break; + + case T_COMPL_ALT: + case T_OR_ALT: + case T_AND_ALT: + case T_NOT_ALT: + case T_XOR_ALT: + case T_ANDASSIGN_ALT: + case T_ORASSIGN_ALT: + case T_XORASSIGN_ALT: + case T_NOTEQUAL_ALT: + switch (static_cast<unsigned int>(prev)) { + case T_LEFTPAREN: + case T_RIGHTPAREN: + case T_LEFTBRACKET: + case T_RIGHTBRACKET: + case T_LEFTBRACE: + case T_RIGHTBRACE: + case T_SEMICOLON: + case T_COMMA: + case T_COLON: + // no insertion between parens/brackets/braces and operators + return false; + + case T_IDENTIFIER: + if (T_NONREPLACABLE_IDENTIFIER == prev || + IS_CATEGORY(prev, KeywordTokenType)) + { + return true; + } + break; + + default: + break; + } + break; + + case T_STAR: + if (T_STAR == prev) + return false; // '*****' do not need to be separated + if (T_GREATER== prev && + (T_MINUS == beforeprev || T_MINUSMINUS == beforeprev) + ) + { + return true; // prevent ->* + } + break; + + case T_POUND: + if (T_POUND == prev) + return true; + break; + } + + // FIXME: else, handle operators separately (will catch to many cases) +// if (IS_CATEGORY(current, OperatorTokenType) && +// IS_CATEGORY(prev, OperatorTokenType)) +// { +// return true; // operators must be delimited always +// } + return false; + } + void shift_tokens (boost::wave::token_id next_id) + { + if (insert_whitespace) { + beforeprev = prev; + prev = next_id; + } + } + +private: + bool insert_whitespace; // enable this component + boost::wave::token_id prev; // the previous analyzed token + boost::wave::token_id beforeprev; // the token before the previous +}; + +/////////////////////////////////////////////////////////////////////////////// +} // namespace util +} // namespace wave +} // namespace boost + +// the suffix header occurs after all of the code +#ifdef BOOST_HAS_ABI_HEADERS +#include BOOST_ABI_SUFFIX +#endif + +#endif // !defined(INSERT_WHITESPACE_DETECTION_HPP_765EF77B_0513_4967_BDD6_6A38148C4C96_INCLUDED) |