summaryrefslogtreecommitdiff
path: root/boost/wave/util/insert_whitespace_detection.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/wave/util/insert_whitespace_detection.hpp')
-rw-r--r--boost/wave/util/insert_whitespace_detection.hpp518
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)