123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- /*=============================================================================
- 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-2012 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(BOOST_INSERT_WHITESPACE_DETECTION_HPP_765EF77B_0513_4967_BDD6_6A38148C4C96_INCLUDED)
- #define BOOST_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 (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 T_UNKNOWN_UNIVERSALCHAR:
- return would_form_universal_char(value);
- default:
- break;
- }
- return false;
- }
- // T_INTLIT
- inline bool
- handle_intlit(boost::wave::token_id prev, boost::wave::token_id /*before*/)
- {
- using namespace boost::wave;
- switch (prev) {
- case T_IDENTIFIER:
- case T_NONREPLACABLE_IDENTIFIER:
- case T_INTLIT:
- case T_FLOATLIT:
- case T_FIXEDPOINTLIT:
- case T_PP_NUMBER:
- return true;
- default:
- break;
- }
- return false;
- }
- // T_FLOATLIT
- inline bool
- handle_floatlit(boost::wave::token_id prev,
- boost::wave::token_id /*before*/)
- {
- using namespace boost::wave;
- switch (prev) {
- case T_IDENTIFIER:
- case T_NONREPLACABLE_IDENTIFIER:
- case T_INTLIT:
- case T_FLOATLIT:
- case T_FIXEDPOINTLIT:
- case T_PP_NUMBER:
- return true;
- default:
- break;
- }
- return false;
- }
- // <% T_LEFTBRACE
- inline bool
- handle_alt_leftbrace(boost::wave::token_id prev,
- boost::wave::token_id /*before*/)
- {
- using namespace boost::wave;
- switch (prev) {
- case T_LESS: // <<%
- case T_SHIFTLEFT: // <<<%
- return true;
- default:
- break;
- }
- return false;
- }
- // <: T_LEFTBRACKET
- inline bool
- handle_alt_leftbracket(boost::wave::token_id prev,
- boost::wave::token_id /*before*/)
- {
- using namespace boost::wave;
- switch (prev) {
- case T_LESS: // <<:
- case T_SHIFTLEFT: // <<<:
- return true;
- default:
- break;
- }
- return false;
- }
- // T_FIXEDPOINTLIT
- inline bool
- handle_fixedpointlit(boost::wave::token_id prev,
- boost::wave::token_id /*before*/)
- {
- using namespace boost::wave;
- switch (prev) {
- case T_IDENTIFIER:
- case T_NONREPLACABLE_IDENTIFIER:
- case T_INTLIT:
- case T_FLOATLIT:
- case T_FIXEDPOINTLIT:
- case T_PP_NUMBER:
- return true;
- default:
- break;
- }
- return false;
- }
- // T_DOT
- inline bool
- handle_dot(boost::wave::token_id prev, boost::wave::token_id before)
- {
- using namespace boost::wave;
- switch (prev) {
- case T_DOT:
- if (T_DOT == before)
- return true; // ...
- break;
- default:
- 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(prev) {
- case T_UNKNOWN_UNIVERSALCHAR: // \?
- case T_QUESTION_MARK: // ??
- return true;
- default:
- break;
- }
- return false;
- }
- // T_NEWLINE
- inline bool
- handle_newline(boost::wave::token_id prev,
- boost::wave::token_id before)
- {
- using namespace boost::wave;
- switch(prev) {
- case TOKEN_FROM_ID('\\', UnknownTokenType): // \ \n
- case T_DIVIDE:
- if (T_QUESTION_MARK == before)
- return true; // ?/\n // may be \\n
- break;
- default:
- break;
- }
- return false;
- }
- inline bool
- handle_parens(boost::wave::token_id prev)
- {
- switch (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 (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 (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 (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 (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 (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;
- default:
- 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(BOOST_INSERT_WHITESPACE_DETECTION_HPP_765EF77B_0513_4967_BDD6_6A38148C4C96_INCLUDED)
|