PageRenderTime 48ms CodeModel.GetById 8ms app.highlight 34ms RepoModel.GetById 2ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/lex/lexer/lexertl/functor.hpp

http://hadesmem.googlecode.com/
C++ Header | 300 lines | 190 code | 39 blank | 71 comment | 28 complexity | 45502bfd1ff98e6a2703630053625e8a MD5 | raw file
  1//  Copyright (c) 2001-2011 Hartmut Kaiser
  2// 
  3//  Distributed under the Boost Software License, Version 1.0. (See accompanying 
  4//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5
  6#if !defined(BOOST_SPIRIT_LEX_LEXER_FUNCTOR_NOV_18_2007_1112PM)
  7#define BOOST_SPIRIT_LEX_LEXER_FUNCTOR_NOV_18_2007_1112PM
  8
  9#if defined(_MSC_VER)
 10#pragma once
 11#endif
 12
 13#include <boost/mpl/bool.hpp>
 14#include <boost/detail/iterator.hpp>
 15#include <boost/detail/workaround.hpp>
 16#include <boost/spirit/home/lex/lexer/pass_flags.hpp>
 17#include <boost/assert.hpp>
 18
 19#if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
 20#define BOOST_SPIRIT_STATIC_EOF 1
 21#define BOOST_SPIRIT_EOF_PREFIX static
 22#else
 23#define BOOST_SPIRIT_EOF_PREFIX 
 24#endif
 25
 26namespace boost { namespace spirit { namespace lex { namespace lexertl
 27{ 
 28    ///////////////////////////////////////////////////////////////////////////
 29    //
 30    //  functor is a template usable as the functor object for the 
 31    //  multi_pass iterator allowing to wrap a lexertl based dfa into a 
 32    //  iterator based interface.
 33    //  
 34    //    Token:      the type of the tokens produced by this functor
 35    //                this needs to expose a constructor with the following
 36    //                prototype:
 37    //
 38    //                Token(std::size_t id, std::size_t state, 
 39    //                      Iterator start, Iterator end)
 40    //
 41    //                where 'id' is the token id, state is the lexer state,
 42    //                this token has been matched in, and 'first' and 'end'  
 43    //                mark the start and the end of the token with respect 
 44    //                to the underlying character stream.
 45    //    FunctorData:
 46    //                this is expected to encapsulate the shared part of the 
 47    //                functor (see lex/lexer/lexertl/functor_data.hpp for an
 48    //                example and documentation).
 49    //    Iterator:   the type of the underlying iterator
 50    //    SupportsActors:
 51    //                this is expected to be a mpl::bool_, if mpl::true_ the
 52    //                functor invokes functors which (optionally) have 
 53    //                been attached to the token definitions.
 54    //    SupportState:
 55    //                this is expected to be a mpl::bool_, if mpl::true_ the
 56    //                functor supports different lexer states, 
 57    //                otherwise no lexer state is supported.
 58    //
 59    ///////////////////////////////////////////////////////////////////////////
 60    template <typename Token
 61      , template <typename, typename, typename, typename> class FunctorData
 62      , typename Iterator = typename Token::iterator_type
 63      , typename SupportsActors = mpl::false_
 64      , typename SupportsState = typename Token::has_state>
 65    class functor
 66    {
 67    public:
 68        typedef typename 
 69            boost::detail::iterator_traits<Iterator>::value_type 
 70        char_type;
 71
 72    private:
 73        // Needed by compilers not implementing the resolution to DR45. For
 74        // reference, see
 75        // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
 76        typedef typename Token::token_value_type token_value_type;
 77        friend class FunctorData<Iterator, SupportsActors, SupportsState
 78          , token_value_type>;
 79
 80        // Helper template allowing to assign a value on exit
 81        template <typename T>
 82        struct assign_on_exit
 83        {
 84            assign_on_exit(T& dst, T const& src)
 85              : dst_(dst), src_(src) {}
 86
 87            ~assign_on_exit()
 88            {
 89                dst_ = src_;
 90            }
 91
 92            T& dst_;
 93            T const& src_;
 94
 95        private:
 96            // silence MSVC warning C4512: assignment operator could not be generated
 97            assign_on_exit& operator= (assign_on_exit const&);
 98        };
 99
100    public:
101        functor()
102#if defined(__PGI)
103          : eof()
104#endif 
105        {}
106
107#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
108        // somehow VC7.1 needs this (meaningless) assignment operator
109        functor& operator=(functor const& rhs)
110        {
111            return *this;
112        }
113#endif
114
115        ///////////////////////////////////////////////////////////////////////
116        // interface to the iterator_policies::split_functor_input policy
117        typedef Token result_type;
118        typedef functor unique;
119        typedef FunctorData<Iterator, SupportsActors, SupportsState
120          , token_value_type> shared;
121
122        BOOST_SPIRIT_EOF_PREFIX result_type const eof;
123
124        ///////////////////////////////////////////////////////////////////////
125        typedef Iterator iterator_type;
126        typedef typename shared::semantic_actions_type semantic_actions_type;
127        typedef typename shared::next_token_functor next_token_functor;
128        typedef typename shared::get_state_name_type get_state_name_type;
129
130        // this is needed to wrap the semantic actions in a proper way
131        typedef typename shared::wrap_action_type wrap_action_type;
132
133        ///////////////////////////////////////////////////////////////////////
134        template <typename MultiPass>
135        static result_type& get_next(MultiPass& mp, result_type& result)
136        {
137            typedef typename result_type::id_type id_type;
138
139            shared& data = mp.shared()->ftor;
140            for(;;) 
141            {
142                if (data.get_first() == data.get_last()) 
143#if defined(BOOST_SPIRIT_STATIC_EOF)
144                    return result = eof;
145#else
146                    return result = mp.ftor.eof;
147#endif
148
149                data.reset_value();
150                Iterator end = data.get_first();
151                std::size_t unique_id = boost::lexer::npos;
152                bool prev_bol = false;
153
154                // lexer matching might change state
155                std::size_t state = data.get_state();
156                std::size_t id = data.next(end, unique_id, prev_bol);
157
158                if (boost::lexer::npos == id) {   // no match
159#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
160                    std::string next;
161                    Iterator it = data.get_first();
162                    for (std::size_t i = 0; i < 10 && it != data.get_last(); ++it, ++i)
163                        next += *it;
164
165                    std::cerr << "Not matched, in state: " << state 
166                              << ", lookahead: >" << next << "<" << std::endl;
167#endif
168                    return result = result_type(0);
169                }
170                else if (0 == id) {         // EOF reached
171#if defined(BOOST_SPIRIT_STATIC_EOF)
172                    return result = eof;
173#else
174                    return result = mp.ftor.eof;
175#endif
176                }
177
178#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
179                {
180                    std::string next;
181                    Iterator it = end;
182                    for (std::size_t i = 0; i < 10 && it != data.get_last(); ++it, ++i)
183                        next += *it;
184
185                    std::cerr << "Matched: " << id << ", in state: " 
186                              << state << ", string: >" 
187                              << std::basic_string<char_type>(data.get_first(), end) << "<"
188                              << ", lookahead: >" << next << "<" << std::endl;
189                    if (data.get_state() != state) {
190                        std::cerr << "Switched to state: " 
191                                  << data.get_state() << std::endl;
192                    }
193                }
194#endif
195                // account for a possibly pending lex::more(), i.e. moving 
196                // data.first_ back to the start of the previously matched token.
197                bool adjusted = data.adjust_start();
198
199                // set the end of the matched input sequence in the token data
200                data.set_end(end);
201
202                // invoke attached semantic actions, if defined, might change
203                // state, id, data.first_, and/or end
204                BOOST_SCOPED_ENUM(pass_flags) pass = 
205                    data.invoke_actions(state, id, unique_id, end);
206
207                if (data.has_value()) {
208                    // return matched token using the token value as set before
209                    // using data.set_value(), advancing 'data.first_' past the 
210                    // matched sequence
211                    assign_on_exit<Iterator> on_exit(data.get_first(), end);
212                    return result = result_type(id_type(id), state, data.get_value());
213                }
214                else if (pass_flags::pass_normal == pass) {
215                    // return matched token, advancing 'data.first_' past the 
216                    // matched sequence
217                    assign_on_exit<Iterator> on_exit(data.get_first(), end);
218                    return result = result_type(id_type(id), state, data.get_first(), end);
219                }
220                else if (pass_flags::pass_fail == pass) {
221#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
222                    std::cerr << "Matching forced to fail" << std::endl; 
223#endif
224                    // if the data.first_ got adjusted above, revert this adjustment
225                    if (adjusted)
226                        data.revert_adjust_start();
227
228                    // one of the semantic actions signaled no-match
229                    data.reset_bol(prev_bol);
230                    if (state != data.get_state())
231                        continue;       // retry matching if state has changed
232
233                    // if the state is unchanged repeating the match wouldn't
234                    // move the input forward, causing an infinite loop
235                    return result = result_type(0);
236                }
237
238#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
239                std::cerr << "Token ignored, continuing matching" << std::endl; 
240#endif
241            // if this token needs to be ignored, just repeat the matching,
242            // while starting right after the current match
243                data.get_first() = end;
244            }
245        }
246
247        // set_state are propagated up to the iterator interface, allowing to 
248        // manipulate the current lexer state through any of the exposed 
249        // iterators.
250        template <typename MultiPass>
251        static std::size_t set_state(MultiPass& mp, std::size_t state) 
252        { 
253            std::size_t oldstate = mp.shared()->ftor.get_state();
254            mp.shared()->ftor.set_state(state);
255
256#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
257            std::cerr << "Switching state from: " << oldstate 
258                      << " to: " << state
259                      << std::endl;
260#endif
261            return oldstate; 
262        }
263
264        template <typename MultiPass>
265        static std::size_t get_state(MultiPass& mp) 
266        { 
267            return mp.shared()->ftor.get_state();
268        }
269
270        template <typename MultiPass>
271        static std::size_t 
272        map_state(MultiPass const& mp, char_type const* statename)  
273        { 
274            return mp.shared()->ftor.get_state_id(statename);
275        }
276
277        // we don't need this, but it must be there
278        template <typename MultiPass>
279        static void destroy(MultiPass const&) {}
280    };
281
282#if defined(BOOST_SPIRIT_STATIC_EOF)
283    ///////////////////////////////////////////////////////////////////////////
284    //  eof token
285    ///////////////////////////////////////////////////////////////////////////
286    template <typename Token
287      , template <typename, typename, typename, typename> class FunctorData
288      , typename Iterator, typename SupportsActors, typename SupportsState>
289    typename functor<Token, FunctorData, Iterator, SupportsActors, SupportsState>::result_type const
290        functor<Token, FunctorData, Iterator, SupportsActors, SupportsState>::eof = 
291            typename functor<Token, FunctorData, Iterator, SupportsActors
292              , SupportsState>::result_type();
293#endif
294
295}}}}
296
297#undef BOOST_SPIRIT_EOF_PREFIX
298#undef BOOST_SPIRIT_STATIC_EOF
299
300#endif