Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/wave/util/interpret_pragma.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

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