| 1 | /*============================================================================= |
|---|
| 2 | Boost.Wave: A Standard compliant C++ preprocessor library |
|---|
| 3 | |
|---|
| 4 | http://www.boost.org/ |
|---|
| 5 | |
|---|
| 6 | Copyright (c) 2001-2005 Hartmut Kaiser. Distributed under the Boost |
|---|
| 7 | Software License, Version 1.0. (See accompanying file |
|---|
| 8 | LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
|---|
| 9 | =============================================================================*/ |
|---|
| 10 | |
|---|
| 11 | #if !defined(INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED) |
|---|
| 12 | #define INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED |
|---|
| 13 | |
|---|
| 14 | #include <string> |
|---|
| 15 | #include <list> |
|---|
| 16 | |
|---|
| 17 | #include <boost/spirit/core.hpp> |
|---|
| 18 | #if SPIRIT_VERSION >= 0x1700 |
|---|
| 19 | #include <boost/spirit/actor/assign_actor.hpp> |
|---|
| 20 | #include <boost/spirit/actor/push_back_actor.hpp> |
|---|
| 21 | #endif // SPIRIT_VERSION >= 0x1700 |
|---|
| 22 | |
|---|
| 23 | #include <boost/wave/wave_config.hpp> |
|---|
| 24 | |
|---|
| 25 | #include <boost/wave/util/pattern_parser.hpp> |
|---|
| 26 | #include <boost/wave/util/macro_helpers.hpp> |
|---|
| 27 | |
|---|
| 28 | #include <boost/wave/token_ids.hpp> |
|---|
| 29 | #include <boost/wave/cpp_exceptions.hpp> |
|---|
| 30 | #include <boost/wave/cpp_iteration_context.hpp> |
|---|
| 31 | #include <boost/wave/language_support.hpp> |
|---|
| 32 | |
|---|
| 33 | #if !defined(spirit_append_actor) |
|---|
| 34 | #if SPIRIT_VERSION >= 0x1700 |
|---|
| 35 | #define spirit_append_actor(actor) boost::spirit::push_back_a(actor) |
|---|
| 36 | #define spirit_assign_actor(actor) boost::spirit::assign_a(actor) |
|---|
| 37 | #else |
|---|
| 38 | #define spirit_append_actor(actor) boost::spirit::append(actor) |
|---|
| 39 | #define spirit_assign_actor(actor) boost::spirit::assign(actor) |
|---|
| 40 | #endif // SPIRIT_VERSION >= 0x1700 |
|---|
| 41 | #endif // !defined(spirit_append_actor) |
|---|
| 42 | |
|---|
| 43 | /////////////////////////////////////////////////////////////////////////////// |
|---|
| 44 | namespace boost { |
|---|
| 45 | namespace wave { |
|---|
| 46 | namespace util { |
|---|
| 47 | |
|---|
| 48 | /////////////////////////////////////////////////////////////////////////////// |
|---|
| 49 | // |
|---|
| 50 | // The function interpret_pragma interprets the given token sequence as the |
|---|
| 51 | // body of a #pragma directive (or parameter to the _Pragma operator) and |
|---|
| 52 | // executes the actions associated with recognized Wave specific options. |
|---|
| 53 | // |
|---|
| 54 | /////////////////////////////////////////////////////////////////////////////// |
|---|
| 55 | template <typename ContextT, typename IteratorT, typename ContainerT> |
|---|
| 56 | inline bool |
|---|
| 57 | interpret_pragma(ContextT &ctx, typename ContextT::token_type const &act_token, |
|---|
| 58 | IteratorT it, IteratorT const &end, ContainerT &pending) |
|---|
| 59 | { |
|---|
| 60 | typedef typename ContextT::token_type token_type; |
|---|
| 61 | typedef typename token_type::string_type string_type; |
|---|
| 62 | |
|---|
| 63 | using namespace cpplexer; |
|---|
| 64 | if (T_IDENTIFIER == token_id(*it) && "wave" == (*it).get_value()) { |
|---|
| 65 | // this is a wave specific option, it should have the form: |
|---|
| 66 | // #pragma wave option(value) |
|---|
| 67 | // where '(value)' is required only for some pragma directives |
|---|
| 68 | // all of the given #pragma operators are forwarded to the supplied |
|---|
| 69 | // context_policy |
|---|
| 70 | using namespace boost::spirit; |
|---|
| 71 | token_type option; |
|---|
| 72 | ContainerT values; |
|---|
| 73 | |
|---|
| 74 | if (!parse (++it, end, |
|---|
| 75 | ( ch_p(T_IDENTIFIER) |
|---|
| 76 | [ |
|---|
| 77 | spirit_assign_actor(option) |
|---|
| 78 | ] |
|---|
| 79 | | pattern_p(KeywordTokenType, TokenTypeMask) |
|---|
| 80 | [ |
|---|
| 81 | spirit_assign_actor(option) |
|---|
| 82 | ] |
|---|
| 83 | | pattern_p(OperatorTokenType|AltExtTokenType, |
|---|
| 84 | ExtTokenTypeMask) // and, bit_and etc. |
|---|
| 85 | [ |
|---|
| 86 | spirit_assign_actor(option) |
|---|
| 87 | ] |
|---|
| 88 | ) |
|---|
| 89 | >> !( ch_p(T_LEFTPAREN) |
|---|
| 90 | >> lexeme_d[ |
|---|
| 91 | *(anychar_p[spirit_append_actor(values)] - ch_p(T_RIGHTPAREN)) |
|---|
| 92 | ] |
|---|
| 93 | >> ch_p(T_RIGHTPAREN) |
|---|
| 94 | ), |
|---|
| 95 | pattern_p(WhiteSpaceTokenType, TokenTypeMask)).hit) |
|---|
| 96 | { |
|---|
| 97 | return false; |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | // remove the falsely matched closing parenthesis |
|---|
| 101 | if (values.size() > 0) { |
|---|
| 102 | if (T_RIGHTPAREN == values.back()) { |
|---|
| 103 | typename ContainerT::reverse_iterator rit = values.rbegin(); |
|---|
| 104 | |
|---|
| 105 | values.erase((++rit).base()); |
|---|
| 106 | } |
|---|
| 107 | else { |
|---|
| 108 | BOOST_WAVE_THROW(preprocess_exception, ill_formed_pragma_option, |
|---|
| 109 | "missing matching ')'", act_token.get_position()); |
|---|
| 110 | } |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | // decode the option (call the context_policy hook) |
|---|
| 114 | if (!ctx.interpret_pragma(pending, option, values, act_token)) |
|---|
| 115 | { |
|---|
| 116 | // unknown #pragma option |
|---|
| 117 | string_type option_str (option.get_value()); |
|---|
| 118 | |
|---|
| 119 | if (values.size() > 0) { |
|---|
| 120 | option_str += "("; |
|---|
| 121 | option_str += impl::as_string(values); |
|---|
| 122 | option_str += ")"; |
|---|
| 123 | } |
|---|
| 124 | BOOST_WAVE_THROW(preprocess_exception, ill_formed_pragma_option, |
|---|
| 125 | option_str.c_str(), act_token.get_position()); |
|---|
| 126 | } |
|---|
| 127 | return true; |
|---|
| 128 | } |
|---|
| 129 | #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 |
|---|
| 130 | else if (T_IDENTIFIER == token_id(*it) && "once" == (*it).get_value()) { |
|---|
| 131 | // #pragma once |
|---|
| 132 | return ctx.add_pragma_once_header(ctx.get_current_filename()); |
|---|
| 133 | } |
|---|
| 134 | #endif |
|---|
| 135 | |
|---|
| 136 | return false; |
|---|
| 137 | } |
|---|
| 138 | |
|---|
| 139 | /////////////////////////////////////////////////////////////////////////////// |
|---|
| 140 | } // namespace util |
|---|
| 141 | } // namespace wave |
|---|
| 142 | } // namespace boost |
|---|
| 143 | |
|---|
| 144 | #endif // !defined(INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED) |
|---|