source: NonGTP/Boost/boost/wave/util/interpret_pragma.hpp @ 857

Revision 857, 5.5 KB checked in by igarcia, 18 years ago (diff)
Line 
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///////////////////////////////////////////////////////////////////////////////
44namespace boost {
45namespace wave {
46namespace 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///////////////////////////////////////////////////////////////////////////////
55template <typename ContextT, typename IteratorT, typename ContainerT>
56inline bool
57interpret_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)
Note: See TracBrowser for help on using the repository browser.