]>
Commit | Line | Data |
---|---|---|
1 | /*============================================================================= | |
2 | Boost.Wave: A Standard compliant C++ preprocessor library | |
3 | ||
4 | http://www.boost.org/ | |
5 | ||
6 | Copyright (c) 2001-2012 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/include/classic_core.hpp> | |
18 | #include <boost/spirit/include/classic_assign_actor.hpp> | |
19 | #include <boost/spirit/include/classic_push_back_actor.hpp> | |
20 | #include <boost/spirit/include/classic_confix.hpp> | |
21 | ||
22 | #include <boost/wave/wave_config.hpp> | |
23 | ||
24 | #include <boost/wave/util/pattern_parser.hpp> | |
25 | #include <boost/wave/util/macro_helpers.hpp> | |
26 | ||
27 | #include <boost/wave/token_ids.hpp> | |
28 | #include <boost/wave/cpp_exceptions.hpp> | |
29 | #include <boost/wave/cpp_iteration_context.hpp> | |
30 | #include <boost/wave/language_support.hpp> | |
31 | ||
32 | #if !defined(spirit_append_actor) | |
33 | #define spirit_append_actor(actor) boost::spirit::classic::push_back_a(actor) | |
34 | #define spirit_assign_actor(actor) boost::spirit::classic::assign_a(actor) | |
35 | #endif // !defined(spirit_append_actor) | |
36 | ||
37 | // this must occur after all of the includes and before any code appears | |
38 | #ifdef BOOST_HAS_ABI_HEADERS | |
39 | #include BOOST_ABI_PREFIX | |
40 | #endif | |
41 | ||
42 | /////////////////////////////////////////////////////////////////////////////// | |
43 | namespace boost { | |
44 | namespace wave { | |
45 | namespace util { | |
46 | ||
47 | /////////////////////////////////////////////////////////////////////////////// | |
48 | // | |
49 | // The function interpret_pragma interprets the given token sequence as the | |
50 | // body of a #pragma directive (or parameter to the _Pragma operator) and | |
51 | // executes the actions associated with recognized Wave specific options. | |
52 | // | |
53 | /////////////////////////////////////////////////////////////////////////////// | |
54 | template <typename ContextT, typename IteratorT, typename ContainerT> | |
55 | inline bool | |
56 | interpret_pragma(ContextT &ctx, typename ContextT::token_type const &act_token, | |
57 | IteratorT it, IteratorT const &end, ContainerT &pending) | |
58 | { | |
59 | typedef typename ContextT::token_type token_type; | |
60 | typedef typename token_type::string_type string_type; | |
61 | ||
62 | using namespace cpplexer; | |
63 | if (T_IDENTIFIER == token_id(*it)) { | |
64 | // check for pragma wave ... | |
65 | if ((*it).get_value() == BOOST_WAVE_PRAGMA_KEYWORD) | |
66 | { | |
67 | // this is a wave specific option, it should have the form: | |
68 | // | |
69 | // #pragma command option(value) | |
70 | // | |
71 | // where | |
72 | // 'command' is the value of the preprocessor constant | |
73 | // BOOST_WAVE_PRAGMA_KEYWORD (defaults to "wave") and | |
74 | // '(value)' is required only for some pragma directives (this is | |
75 | // optional) | |
76 | // | |
77 | // All recognized #pragma operators are forwarded to the supplied | |
78 | // preprocessing hook. | |
79 | using namespace boost::spirit::classic; | |
80 | token_type option; | |
81 | ContainerT values; | |
82 | ||
83 | if (!parse (++it, end, | |
84 | ( ch_p(T_IDENTIFIER) | |
85 | [ | |
86 | spirit_assign_actor(option) | |
87 | ] | |
88 | | pattern_p(KeywordTokenType, | |
89 | TokenTypeMask|PPTokenFlag) | |
90 | [ | |
91 | spirit_assign_actor(option) | |
92 | ] | |
93 | | pattern_p(OperatorTokenType|AltExtTokenType, | |
94 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. | |
95 | [ | |
96 | spirit_assign_actor(option) | |
97 | ] | |
98 | | pattern_p(BoolLiteralTokenType, | |
99 | TokenTypeMask|PPTokenFlag) | |
100 | [ | |
101 | spirit_assign_actor(option) | |
102 | ] | |
103 | ) | |
104 | >> !comment_nest_p( | |
105 | ch_p(T_LEFTPAREN), | |
106 | ch_p(T_RIGHTPAREN) | |
107 | )[spirit_assign_actor(values)], | |
108 | pattern_p(WhiteSpaceTokenType, TokenTypeMask|PPTokenFlag)).hit) | |
109 | { | |
110 | typename ContextT::string_type msg( | |
111 | impl::as_string<string_type>(it, end)); | |
112 | BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, | |
113 | ill_formed_pragma_option, | |
114 | msg.c_str(), act_token.get_position()); | |
115 | return false; | |
116 | } | |
117 | ||
118 | // remove the falsely matched surrounding parenthesis's | |
119 | if (values.size() >= 2) { | |
120 | BOOST_ASSERT(T_LEFTPAREN == values.front() && T_RIGHTPAREN == values.back()); | |
121 | values.erase(values.begin()); | |
122 | typename ContainerT::reverse_iterator rit = values.rbegin(); | |
123 | values.erase((++rit).base()); | |
124 | } | |
125 | ||
126 | // decode the option (call the context_policy hook) | |
127 | if (!ctx.get_hooks().interpret_pragma( | |
128 | ctx.derived(), pending, option, values, act_token)) | |
129 | { | |
130 | // unknown #pragma option | |
131 | string_type option_str ((*it).get_value()); | |
132 | ||
133 | option_str += option.get_value(); | |
134 | if (values.size() > 0) { | |
135 | option_str += "("; | |
136 | option_str += impl::as_string(values); | |
137 | option_str += ")"; | |
138 | } | |
139 | BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, | |
140 | ill_formed_pragma_option, | |
141 | option_str.c_str(), act_token.get_position()); | |
142 | return false; | |
143 | } | |
144 | return true; | |
145 | } | |
146 | #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
147 | else if ((*it).get_value() == "once") { | |
148 | // #pragma once | |
149 | return ctx.add_pragma_once_header(act_token, ctx.get_current_filename()); | |
150 | } | |
151 | #endif | |
152 | #if BOOST_WAVE_SUPPORT_PRAGMA_MESSAGE != 0 | |
153 | else if ((*it).get_value() == "message") { | |
154 | // #pragma message(...) or #pragma message ... | |
155 | using namespace boost::spirit::classic; | |
156 | ContainerT values; | |
157 | ||
158 | if (!parse (++it, end, | |
159 | ( ( ch_p(T_LEFTPAREN) | |
160 | >> lexeme_d[ | |
161 | *(anychar_p[spirit_append_actor(values)] - ch_p(T_RIGHTPAREN)) | |
162 | ] | |
163 | >> ch_p(T_RIGHTPAREN) | |
164 | ) | |
165 | | lexeme_d[ | |
166 | *(anychar_p[spirit_append_actor(values)] - ch_p(T_NEWLINE)) | |
167 | ] | |
168 | ), | |
169 | pattern_p(WhiteSpaceTokenType, TokenTypeMask|PPTokenFlag) | |
170 | ).hit | |
171 | ) | |
172 | { | |
173 | typename ContextT::string_type msg( | |
174 | impl::as_string<string_type>(it, end)); | |
175 | BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, | |
176 | ill_formed_pragma_message, | |
177 | msg.c_str(), act_token.get_position()); | |
178 | return false; | |
179 | } | |
180 | ||
181 | // remove the falsely matched closing parenthesis/newline | |
182 | if (values.size() > 0) { | |
183 | BOOST_ASSERT(T_RIGHTPAREN == values.back() || T_NEWLINE == values.back()); | |
184 | typename ContainerT::reverse_iterator rit = values.rbegin(); | |
185 | values.erase((++rit).base()); | |
186 | } | |
187 | ||
188 | // output the message itself | |
189 | typename ContextT::string_type msg(impl::as_string(values)); | |
190 | BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, | |
191 | pragma_message_directive, | |
192 | msg.c_str(), act_token.get_position()); | |
193 | return false; | |
194 | } | |
195 | #endif | |
196 | } | |
197 | return false; | |
198 | } | |
199 | ||
200 | /////////////////////////////////////////////////////////////////////////////// | |
201 | } // namespace util | |
202 | } // namespace wave | |
203 | } // namespace boost | |
204 | ||
205 | // the suffix header occurs after all of the code | |
206 | #ifdef BOOST_HAS_ABI_HEADERS | |
207 | #include BOOST_ABI_SUFFIX | |
208 | #endif | |
209 | ||
210 | #endif // !defined(INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED) |