Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:15

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 // 
0003 //  Distributed under the Boost Software License, Version 1.0. (See accompanying 
0004 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #if !defined(BOOST_SPIRIT_LEX_LEXER_FUNCTOR_NOV_18_2007_1112PM)
0007 #define BOOST_SPIRIT_LEX_LEXER_FUNCTOR_NOV_18_2007_1112PM
0008 
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012 
0013 #include <boost/mpl/bool.hpp>
0014 #include <boost/detail/workaround.hpp>
0015 #include <boost/spirit/home/lex/lexer/pass_flags.hpp>
0016 #include <boost/assert.hpp>
0017 #include <iterator> // for std::iterator_traits
0018 
0019 #if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
0020 #define BOOST_SPIRIT_STATIC_EOF 1
0021 #define BOOST_SPIRIT_EOF_PREFIX static
0022 #else
0023 #define BOOST_SPIRIT_EOF_PREFIX 
0024 #endif
0025 
0026 namespace boost { namespace spirit { namespace lex { namespace lexertl
0027 { 
0028     ///////////////////////////////////////////////////////////////////////////
0029     //
0030     //  functor is a template usable as the functor object for the 
0031     //  multi_pass iterator allowing to wrap a lexertl based dfa into a 
0032     //  iterator based interface.
0033     //  
0034     //    Token:      the type of the tokens produced by this functor
0035     //                this needs to expose a constructor with the following
0036     //                prototype:
0037     //
0038     //                Token(std::size_t id, std::size_t state, 
0039     //                      Iterator start, Iterator end)
0040     //
0041     //                where 'id' is the token id, state is the lexer state,
0042     //                this token has been matched in, and 'first' and 'end'  
0043     //                mark the start and the end of the token with respect 
0044     //                to the underlying character stream.
0045     //    FunctorData:
0046     //                this is expected to encapsulate the shared part of the 
0047     //                functor (see lex/lexer/lexertl/functor_data.hpp for an
0048     //                example and documentation).
0049     //    Iterator:   the type of the underlying iterator
0050     //    SupportsActors:
0051     //                this is expected to be a mpl::bool_, if mpl::true_ the
0052     //                functor invokes functors which (optionally) have 
0053     //                been attached to the token definitions.
0054     //    SupportState:
0055     //                this is expected to be a mpl::bool_, if mpl::true_ the
0056     //                functor supports different lexer states, 
0057     //                otherwise no lexer state is supported.
0058     //
0059     ///////////////////////////////////////////////////////////////////////////
0060     template <typename Token
0061       , template <typename, typename, typename, typename> class FunctorData
0062       , typename Iterator = typename Token::iterator_type
0063       , typename SupportsActors = mpl::false_
0064       , typename SupportsState = typename Token::has_state>
0065     class functor
0066     {
0067     public:
0068         typedef typename 
0069             std::iterator_traits<Iterator>::value_type 
0070         char_type;
0071 
0072     private:
0073         // Needed by compilers not implementing the resolution to DR45. For
0074         // reference, see
0075         // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
0076         typedef typename Token::token_value_type token_value_type;
0077         friend class FunctorData<Iterator, SupportsActors, SupportsState
0078           , token_value_type>;
0079 
0080 #ifdef _MSC_VER
0081 #  pragma warning(push)
0082 #  pragma warning(disable: 4512) // assignment operator could not be generated.
0083 #endif
0084         // Helper template allowing to assign a value on exit
0085         template <typename T>
0086         struct assign_on_exit
0087         {
0088             assign_on_exit(T& dst, T const& src)
0089               : dst_(dst), src_(src) {}
0090 
0091             ~assign_on_exit()
0092             {
0093                 dst_ = src_;
0094             }
0095 
0096             T& dst_;
0097             T const& src_;
0098         };
0099 #ifdef _MSC_VER
0100 #  pragma warning(pop)
0101 #endif
0102 
0103     public:
0104         functor() {}
0105 
0106 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
0107         // somehow VC7.1 needs this (meaningless) assignment operator
0108         functor& operator=(functor const& rhs)
0109         {
0110             return *this;
0111         }
0112 #endif
0113 
0114         ///////////////////////////////////////////////////////////////////////
0115         // interface to the iterator_policies::split_functor_input policy
0116         typedef Token result_type;
0117         typedef functor unique;
0118         typedef FunctorData<Iterator, SupportsActors, SupportsState
0119           , token_value_type> shared;
0120 
0121         BOOST_SPIRIT_EOF_PREFIX result_type const eof;
0122 
0123         ///////////////////////////////////////////////////////////////////////
0124         typedef Iterator iterator_type;
0125         typedef typename shared::semantic_actions_type semantic_actions_type;
0126         typedef typename shared::next_token_functor next_token_functor;
0127         typedef typename shared::get_state_name_type get_state_name_type;
0128 
0129         // this is needed to wrap the semantic actions in a proper way
0130         typedef typename shared::wrap_action_type wrap_action_type;
0131 
0132         ///////////////////////////////////////////////////////////////////////
0133         template <typename MultiPass>
0134         static result_type& get_next(MultiPass& mp, result_type& result)
0135         {
0136             typedef typename result_type::id_type id_type;
0137 
0138             shared& data = mp.shared()->ftor;
0139             for(;;) 
0140             {
0141                 if (data.get_first() == data.get_last()) 
0142 #if defined(BOOST_SPIRIT_STATIC_EOF)
0143                     return result = eof;
0144 #else
0145                     return result = mp.ftor.eof;
0146 #endif
0147 
0148                 data.reset_value();
0149                 Iterator end = data.get_first();
0150                 std::size_t unique_id = boost::lexer::npos;
0151                 bool prev_bol = false;
0152 
0153                 // lexer matching might change state
0154                 std::size_t state = data.get_state();
0155                 std::size_t id = data.next(end, unique_id, prev_bol);
0156 
0157                 if (boost::lexer::npos == id) {   // no match
0158 #if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
0159                     std::string next;
0160                     Iterator it = data.get_first();
0161                     for (std::size_t i = 0; i < 10 && it != data.get_last(); ++it, ++i)
0162                         next += *it;
0163 
0164                     std::cerr << "Not matched, in state: " << state 
0165                               << ", lookahead: >" << next << "<" << std::endl;
0166 #endif
0167                     return result = result_type(0);
0168                 }
0169                 else if (0 == id) {         // EOF reached
0170 #if defined(BOOST_SPIRIT_STATIC_EOF)
0171                     return result = eof;
0172 #else
0173                     return result = mp.ftor.eof;
0174 #endif
0175                 }
0176 
0177 #if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
0178                 {
0179                     std::string next;
0180                     Iterator it = end;
0181                     for (std::size_t i = 0; i < 10 && it != data.get_last(); ++it, ++i)
0182                         next += *it;
0183 
0184                     std::cerr << "Matched: " << id << ", in state: " 
0185                               << state << ", string: >" 
0186                               << std::basic_string<char_type>(data.get_first(), end) << "<"
0187                               << ", lookahead: >" << next << "<" << std::endl;
0188                     if (data.get_state() != state) {
0189                         std::cerr << "Switched to state: " 
0190                                   << data.get_state() << std::endl;
0191                     }
0192                 }
0193 #endif
0194                 // account for a possibly pending lex::more(), i.e. moving 
0195                 // data.first_ back to the start of the previously matched token.
0196                 bool adjusted = data.adjust_start();
0197 
0198                 // set the end of the matched input sequence in the token data
0199                 data.set_end(end);
0200 
0201                 // invoke attached semantic actions, if defined, might change
0202                 // state, id, data.first_, and/or end
0203                 BOOST_SCOPED_ENUM(pass_flags) pass = 
0204                     data.invoke_actions(state, id, unique_id, end);
0205 
0206                 if (data.has_value()) {
0207                     // return matched token using the token value as set before
0208                     // using data.set_value(), advancing 'data.first_' past the 
0209                     // matched sequence
0210                     assign_on_exit<Iterator> on_exit(data.get_first(), end);
0211                     return result = result_type(id_type(id), state, data.get_value());
0212                 }
0213                 else if (pass_flags::pass_normal == pass) {
0214                     // return matched token, advancing 'data.first_' past the 
0215                     // matched sequence
0216                     assign_on_exit<Iterator> on_exit(data.get_first(), end);
0217                     return result = result_type(id_type(id), state, data.get_first(), end);
0218                 }
0219                 else if (pass_flags::pass_fail == pass) {
0220 #if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
0221                     std::cerr << "Matching forced to fail" << std::endl; 
0222 #endif
0223                     // if the data.first_ got adjusted above, revert this adjustment
0224                     if (adjusted)
0225                         data.revert_adjust_start();
0226 
0227                     // one of the semantic actions signaled no-match
0228                     data.reset_bol(prev_bol);
0229                     if (state != data.get_state())
0230                         continue;       // retry matching if state has changed
0231 
0232                     // if the state is unchanged repeating the match wouldn't
0233                     // move the input forward, causing an infinite loop
0234                     return result = result_type(0);
0235                 }
0236 
0237 #if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
0238                 std::cerr << "Token ignored, continuing matching" << std::endl; 
0239 #endif
0240             // if this token needs to be ignored, just repeat the matching,
0241             // while starting right after the current match
0242                 data.get_first() = end;
0243             }
0244         }
0245 
0246         // set_state are propagated up to the iterator interface, allowing to 
0247         // manipulate the current lexer state through any of the exposed 
0248         // iterators.
0249         template <typename MultiPass>
0250         static std::size_t set_state(MultiPass& mp, std::size_t state) 
0251         { 
0252             std::size_t oldstate = mp.shared()->ftor.get_state();
0253             mp.shared()->ftor.set_state(state);
0254 
0255 #if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
0256             std::cerr << "Switching state from: " << oldstate 
0257                       << " to: " << state
0258                       << std::endl;
0259 #endif
0260             return oldstate; 
0261         }
0262 
0263         template <typename MultiPass>
0264         static std::size_t get_state(MultiPass& mp) 
0265         { 
0266             return mp.shared()->ftor.get_state();
0267         }
0268 
0269         template <typename MultiPass>
0270         static std::size_t 
0271         map_state(MultiPass const& mp, char_type const* statename)  
0272         { 
0273             return mp.shared()->ftor.get_state_id(statename);
0274         }
0275 
0276         // we don't need this, but it must be there
0277         template <typename MultiPass>
0278         static void destroy(MultiPass const&) {}
0279     };
0280 
0281 #if defined(BOOST_SPIRIT_STATIC_EOF)
0282     ///////////////////////////////////////////////////////////////////////////
0283     //  eof token
0284     ///////////////////////////////////////////////////////////////////////////
0285     template <typename Token
0286       , template <typename, typename, typename, typename> class FunctorData
0287       , typename Iterator, typename SupportsActors, typename SupportsState>
0288     typename functor<Token, FunctorData, Iterator, SupportsActors, SupportsState>::result_type const
0289         functor<Token, FunctorData, Iterator, SupportsActors, SupportsState>::eof = 
0290             typename functor<Token, FunctorData, Iterator, SupportsActors
0291               , SupportsState>::result_type();
0292 #endif
0293 
0294 }}}}
0295 
0296 #undef BOOST_SPIRIT_EOF_PREFIX
0297 #undef BOOST_SPIRIT_STATIC_EOF
0298 
0299 #endif