📄 cpp_iterator.hpp
字号:
make_ref_transform_iterator(end, get_value),
std::inserter(toexpand, toexpand.end()));
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded);
// replace all remaining (== undefined) identifiers with an integer literal '0'
typename token_sequence_type::iterator exp_end = expanded.end();
for (typename token_sequence_type::iterator exp_it = expanded.begin();
exp_it != exp_end; ++exp_it)
{
using namespace boost::wave;
token_id id = token_id(*exp_it);
if (IS_CATEGORY(id, IdentifierTokenType) ||
IS_CATEGORY(id, KeywordTokenType))
{
(*exp_it).set_token_id(T_INTLIT);
(*exp_it).set_value("0");
}
}
#if BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS != 0
{
string_type outstr(boost::wave::util::impl::as_string(toexpand));
outstr += "(" + boost::wave::util::impl::as_string(expanded) + ")";
BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT << "#elif " << outstr << std::endl;
}
#endif
// parse the expression and enter the #elif block
ctx.enter_elif_block(grammars::expression_grammar_gen<result_type>::
evaluate(expanded.begin(), expanded.end(), act_pos,
ctx.get_if_block_status()));
}
///////////////////////////////////////////////////////////////////////////////
//
// on_illformed(): handles the illegal directive
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::on_illformed(
typename result_type::string_type const &s)
{
BOOST_ASSERT(ctx.get_if_block_status());
BOOST_WAVE_THROW(preprocess_exception, ill_formed_directive, s.c_str(),
act_pos);
}
///////////////////////////////////////////////////////////////////////////////
//
// on_line(): handle #line directives
//
///////////////////////////////////////////////////////////////////////////////
namespace {
template <typename IteratorT, typename StringT>
bool retrieve_line_info (IteratorT first, IteratorT const &last,
int &line, StringT &file)
{
using namespace boost::wave;
if (T_INTLIT == token_id(*first)) {
// extract line number
using namespace std; // some systems have atoi in namespace std
line = atoi((*first).get_value().c_str());
// extract file name (if it is given)
while (++first != last && IS_CATEGORY(*first, WhiteSpaceTokenType))
/**/; // skip whitespace
if (first != last) {
if (T_STRINGLIT != token_id(*first))
return false;
StringT const &file_lit = (*first).get_value();
if ('L' == file_lit[0])
return false; // shouldn't be a wide character string
file = file_lit.substr(1, file_lit.size()-2);
}
return true;
}
return false;
}
}
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::on_line(
typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end)
{
BOOST_ASSERT(ctx.get_if_block_status());
// Try to extract the line number and file name from the given token list
// directly. If that fails, preprocess the whole token sequence and try again
// to extract this information.
token_sequence_type expanded;
get_token_value<result_type, parse_node_type> get_value;
typedef typename ref_transform_iterator_generator<
get_token_value<result_type, parse_node_type>,
typename parse_tree_type::const_iterator
>::type const_tree_iterator_t;
const_tree_iterator_t first = make_ref_transform_iterator(begin, get_value);
const_tree_iterator_t last = make_ref_transform_iterator(end, get_value);
// try to interpret the #line body as a number followed by an optional
// string literal
int line = 0;
string_type file_name;
if (!retrieve_line_info(first, last, line, file_name)) {
// preprocess the body of this #line message
token_sequence_type toexpand;
std::copy(first, make_ref_transform_iterator(end, get_value),
std::inserter(toexpand, toexpand.end()));
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(),
expanded, false);
if (!retrieve_line_info(expanded.begin(), expanded.end(), line,
file_name))
{
BOOST_WAVE_THROW(preprocess_exception, bad_line_statement,
boost::wave::util::impl::as_string(expanded).c_str(), act_pos)
}
}
// the queues should be empty at this point
BOOST_ASSERT(unput_queue.empty());
BOOST_ASSERT(pending_queue.empty());
if (!file_name.empty()) // reuse current file name
act_pos.set_file(file_name.c_str());
act_pos.set_line(line);
// last_line = act_token.get_position().get_line();
//typename result_type::position_type nextline_pos = act_pos;
//
// nextline_pos.set_line(nextline_pos.get_line() + 1);
iter_ctx->first.set_position(act_pos);
must_emit_line_directive = true;
}
///////////////////////////////////////////////////////////////////////////////
//
// on_error(): handle #error directives
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::on_error(
typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end)
{
BOOST_ASSERT(ctx.get_if_block_status());
// preprocess the given sequence into the provided list
token_sequence_type expanded;
get_token_value<result_type, parse_node_type> get_value;
typename ref_transform_iterator_generator<
get_token_value<result_type, parse_node_type>,
typename parse_tree_type::const_iterator
>::type first = make_ref_transform_iterator(begin, get_value);
#if BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY != 0
// preprocess the body of this #error message
token_sequence_type toexpand;
std::copy(first, make_ref_transform_iterator(end, get_value),
std::inserter(toexpand, toexpand.end()));
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
false);
#else
// simply copy the body of this #error message to the issued diagnostic
// message
std::copy(first, make_ref_transform_iterator(end, get_value),
std::inserter(expanded, expanded.end()));
#endif
// report the corresponding error
BOOST_WAVE_THROW(preprocess_exception, error_directive,
boost::wave::util::impl::as_string(expanded).c_str(), act_pos);
}
#if BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0
///////////////////////////////////////////////////////////////////////////////
//
// on_warning(): handle #warning directives
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::on_warning(
typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end)
{
BOOST_ASSERT(ctx.get_if_block_status());
// preprocess the given sequence into the provided list
token_sequence_type expanded;
get_token_value<result_type, parse_node_type> get_value;
typename ref_transform_iterator_generator<
get_token_value<result_type, parse_node_type>,
typename parse_tree_type::const_iterator
>::type first = make_ref_transform_iterator(begin, get_value);
#if BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY != 0
// preprocess the body of this #warning message
token_sequence_type toexpand;
std::copy(first, make_ref_transform_iterator(end, get_value),
std::inserter(toexpand, toexpand.end()));
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
false);
#else
// simply copy the body of this #warning message to the issued diagnostic
// message
std::copy(first, make_ref_transform_iterator(end, get_value),
std::inserter(expanded, expanded.end()));
#endif
// report the corresponding error
BOOST_WAVE_THROW(preprocess_exception, warning_directive,
boost::wave::util::impl::as_string(expanded).c_str(), act_pos);
}
#endif // BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0
///////////////////////////////////////////////////////////////////////////////
//
// on_pragma(): handle #pragma directives
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline bool
pp_iterator_functor<ContextT>::on_pragma(
typename parse_tree_type::const_iterator const &begin,
typename parse_tree_type::const_iterator const &end)
{
using namespace boost::wave;
BOOST_ASSERT(ctx.get_if_block_status());
// Look at the pragma token sequence and decide, if the first token is STDC
// (see C99 standard [6.10.6.2]), if it is, the sequence must _not_ be
// preprocessed.
token_sequence_type expanded;
get_token_value<result_type, parse_node_type> get_value;
typedef typename ref_transform_iterator_generator<
get_token_value<result_type, parse_node_type>,
typename parse_tree_type::const_iterator
>::type const_tree_iterator_t;
const_tree_iterator_t first = make_ref_transform_iterator(begin, get_value);
const_tree_iterator_t last = make_ref_transform_iterator(end, get_value);
expanded.push_back(result_type(T_PP_PRAGMA, "#pragma", act_token.get_position()));
expanded.push_back(result_type(T_SPACE, " ", act_token.get_position()));
while (++first != last && IS_CATEGORY(*first, WhiteSpaceTokenType))
expanded.push_back(*first); // skip whitespace
if (first != last) {
if (T_IDENTIFIER == token_id(*first) &&
boost::wave::need_c99(ctx.get_language()) &&
(*first).get_value() == "STDC")
{
// do _not_ preprocess the token sequence
std::copy(first, last, std::inserter(expanded, expanded.end()));
}
else {
#if BOOST_WAVE_PREPROCESS_PRAGMA_BODY != 0
// preprocess the given tokensequence
token_sequence_type toexpand;
std::copy(first, last, std::inserter(toexpand, toexpand.end()));
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(),
expanded, false);
#else
// do _not_ preprocess the token sequence
std::copy(first, last, std::inserter(expanded, expanded.end()));
#endif
}
}
expanded.push_back(result_type(T_NEWLINE, "\n", act_token.get_position()));
// the queues should be empty at this point
BOOST_ASSERT(unput_queue.empty());
BOOST_ASSERT(pending_queue.empty());
// try to interpret the expanded #pragma body
token_sequence_type pending;
if (interpret_pragma(expanded, pending)) {
// if there is some replacement text, insert it into the pending queue
if (pending.size() > 0)
pending_queue.splice(pending_queue.begin(), pending);
return true; // this #pragma was successfully recognized
}
#if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
// Move the resulting token sequence into the pending_queue, so it will be
// returned to the caller.
pending_queue.splice(pending_queue.begin(), expanded);
return false; // return the whole #pragma directive
#else
return true; // skip the #pragma at all
#endif
}
template <typename ContextT>
inline bool
pp_iterator_functor<ContextT>::interpret_pragma(
token_sequence_type const &pragma_body, token_sequence_type &result)
{
using namespace cpplexer;
typename token_sequence_type::const_iterator end = pragma_body.end();
typename token_sequence_type::const_iterator it = pragma_body.begin();
for (++it; it != end && IS_CATEGORY(*it, WhiteSpaceTokenType); ++it)
/**/; // skip whitespace
if (it == end) // eof reached
return false;
return boost::wave::util::interpret_pragma(ctx, act_token, it, end, result);
}
///////////////////////////////////////////////////////////////////////////////
} // namespace impl
//////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -