Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 //  Copyright (c)      2010 Bryce Lelbach
0003 //
0004 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #if !defined(BOOST_SPIRIT_LEX_STATE_SWITCHER_SEP_23_2007_0714PM)
0008 #define BOOST_SPIRIT_LEX_STATE_SWITCHER_SEP_23_2007_0714PM
0009 
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013 
0014 #include <boost/spirit/home/support/info.hpp>
0015 #include <boost/spirit/home/qi/detail/attributes.hpp>
0016 #include <boost/spirit/home/support/common_terminals.hpp>
0017 #include <boost/spirit/home/support/string_traits.hpp>
0018 #include <boost/spirit/home/support/has_semantic_action.hpp>
0019 #include <boost/spirit/home/support/handles_container.hpp>
0020 #include <boost/spirit/home/qi/skip_over.hpp>
0021 #include <boost/spirit/home/qi/domain.hpp>
0022 #include <boost/spirit/home/qi/parser.hpp>
0023 #include <boost/spirit/home/qi/meta_compiler.hpp>
0024 
0025 namespace boost { namespace spirit
0026 {
0027     ///////////////////////////////////////////////////////////////////////////
0028     // Enablers
0029     ///////////////////////////////////////////////////////////////////////////
0030 
0031     // enables set_state(s)
0032     template <typename A0>
0033     struct use_terminal<qi::domain
0034       , terminal_ex<tag::set_state, fusion::vector1<A0> >
0035     > : traits::is_string<A0> {};
0036 
0037     // enables *lazy* set_state(s)
0038     template <>
0039     struct use_lazy_terminal<
0040         qi::domain, tag::set_state, 1
0041     > : mpl::true_ {};
0042 
0043     // enables in_state(s)[p]
0044     template <typename A0>
0045     struct use_directive<qi::domain
0046       , terminal_ex<tag::in_state, fusion::vector1<A0> >
0047     > : traits::is_string<A0> {};
0048 
0049     // enables *lazy* in_state(s)[p]
0050     template <>
0051     struct use_lazy_directive<
0052         qi::domain, tag::in_state, 1
0053     > : mpl::true_ {};
0054 
0055 }}
0056 
0057 namespace boost { namespace spirit { namespace qi
0058 {
0059 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0060     using spirit::set_state;
0061     using spirit::in_state;
0062 #endif
0063     using spirit::set_state_type;
0064     using spirit::in_state_type;
0065 
0066     ///////////////////////////////////////////////////////////////////////////
0067     namespace detail
0068     {
0069         template <typename Iterator>
0070         inline std::size_t
0071         set_lexer_state(Iterator& it, std::size_t state)
0072         {
0073             return it.set_state(state);
0074         }
0075 
0076         template <typename Iterator, typename Char>
0077         inline std::size_t
0078         set_lexer_state(Iterator& it, Char const* statename)
0079         {
0080             std::size_t state = it.map_state(statename);
0081 
0082             //  If the following assertion fires you probably used the
0083             //  set_state(...) or in_state(...)[...] lexer state switcher with
0084             //  a lexer state name unknown to the lexer (no token definitions
0085             //  have been associated with this lexer state).
0086             BOOST_ASSERT(std::size_t(~0) != state);
0087             return it.set_state(state);
0088         }
0089     }
0090 
0091     ///////////////////////////////////////////////////////////////////////////
0092     //  Parser switching the state of the underlying lexer component.
0093     //  This parser gets used for the set_state(...) construct.
0094     ///////////////////////////////////////////////////////////////////////////
0095     template <typename State>
0096     struct state_switcher
0097       : primitive_parser<state_switcher<State> >
0098     {
0099         typedef typename 
0100             remove_const<typename traits::char_type_of<State>::type>::type 
0101         char_type;
0102         typedef std::basic_string<char_type> string_type;
0103 
0104         template <typename Context, typename Iterator>
0105         struct attribute
0106         {
0107             typedef unused_type type;
0108         };
0109 
0110         state_switcher(char_type const* state)
0111           : state(state) {}
0112 
0113         template <typename Iterator, typename Context
0114           , typename Skipper, typename Attribute>
0115         bool parse(Iterator& first, Iterator const& last
0116           , Context& /*context*/, Skipper const& skipper
0117           , Attribute& /*attr*/) const
0118         {
0119             qi::skip_over(first, last, skipper);   // always do a pre-skip
0120 
0121             // just switch the state and return success
0122             detail::set_lexer_state(first, state.c_str());
0123             return true;
0124         }
0125 
0126         template <typename Context>
0127         info what(Context& /*context*/) const
0128         {
0129             return info("set_state");
0130         }
0131 
0132         string_type state;
0133     };
0134 
0135     ///////////////////////////////////////////////////////////////////////////
0136     namespace detail
0137     {
0138 #ifdef _MSC_VER
0139 #  pragma warning(push)
0140 #  pragma warning(disable: 4512) // assignment operator could not be generated.
0141 #endif
0142         template <typename Iterator>
0143         struct reset_state_on_exit
0144         {
0145             template <typename State>
0146             reset_state_on_exit(Iterator& it_, State state_)
0147               : it(it_)
0148               , state(set_lexer_state(it_, traits::get_c_string(state_))) 
0149             {}
0150 
0151             ~reset_state_on_exit()
0152             {
0153                 // reset the state of the underlying lexer instance
0154                 set_lexer_state(it, state);
0155             }
0156 
0157             Iterator& it;
0158             std::size_t state;
0159         };
0160 #ifdef _MSC_VER
0161 #  pragma warning(pop)
0162 #endif
0163     }
0164 
0165     ///////////////////////////////////////////////////////////////////////////
0166     // Parser, which switches the state of the underlying lexer component
0167     // for the execution of the embedded sub-parser, switching the state back
0168     // afterwards. This parser gets used for the in_state(...)[p] construct.
0169     ///////////////////////////////////////////////////////////////////////////
0170     template <typename Subject, typename State>
0171     struct state_switcher_context 
0172       : unary_parser<state_switcher_context<Subject, State> >
0173     {
0174         typedef Subject subject_type;
0175         typedef typename traits::char_type_of<State>::type char_type;
0176         typedef typename remove_const<char_type>::type non_const_char_type;
0177 
0178         template <typename Context, typename Iterator>
0179         struct attribute
0180         {
0181             typedef typename
0182                 traits::attribute_of<subject_type, Context, Iterator>::type
0183             type;
0184         };
0185 
0186         state_switcher_context(Subject const& subject
0187               , typename add_reference<State>::type state)
0188           : subject(subject), state(state) {}
0189 
0190         // The following conversion constructors are needed to make the 
0191         // in_state_switcher template usable
0192         template <typename String>
0193         state_switcher_context(
0194                 state_switcher_context<Subject, String> const& rhs)
0195           : subject(rhs.subject), state(traits::get_c_string(rhs.state)) {}
0196 
0197         template <typename Iterator, typename Context
0198           , typename Skipper, typename Attribute>
0199         bool parse(Iterator& first, Iterator const& last
0200           , Context& context, Skipper const& skipper
0201           , Attribute& attr) const
0202         {
0203             qi::skip_over(first, last, skipper);   // always do a pre-skip
0204 
0205             // the state has to be reset at exit in any case
0206             detail::reset_state_on_exit<Iterator> guard(first, state);
0207             return subject.parse(first, last, context, skipper, attr);
0208         }
0209 
0210         template <typename Context>
0211         info what(Context& context) const
0212         {
0213             return info("in_state", subject.what(context));
0214         }
0215 
0216         Subject subject;
0217         State state;
0218     };
0219 
0220     ///////////////////////////////////////////////////////////////////////////
0221     // Parser generators: make_xxx function (objects)
0222     ///////////////////////////////////////////////////////////////////////////
0223     template <typename Modifiers, typename State>
0224     struct make_primitive<terminal_ex<tag::set_state, fusion::vector1<State> >
0225       , Modifiers, typename enable_if<traits::is_string<State> >::type>
0226     {
0227         typedef typename add_const<State>::type const_string;
0228         typedef state_switcher<const_string> result_type;
0229 
0230         template <typename Terminal>
0231         result_type operator()(Terminal const& term, unused_type) const
0232         {
0233             return result_type(traits::get_c_string(fusion::at_c<0>(term.args)));
0234         }
0235     };
0236 
0237     template <typename State, typename Subject, typename Modifiers>
0238     struct make_directive<terminal_ex<tag::in_state, fusion::vector1<State> >
0239       , Subject, Modifiers>
0240     {
0241         typedef typename add_const<State>::type const_string;
0242         typedef state_switcher_context<Subject, const_string> result_type;
0243 
0244         template <typename Terminal>
0245         result_type operator()(Terminal const& term, Subject const& subject
0246           , unused_type) const
0247         {
0248             return result_type(subject, fusion::at_c<0>(term.args));
0249         }
0250     };
0251 }}}
0252 
0253 namespace boost { namespace spirit { namespace traits
0254 {
0255     ///////////////////////////////////////////////////////////////////////////
0256     template <typename Subject, typename State>
0257     struct has_semantic_action<qi::state_switcher_context<Subject, State> >
0258       : unary_has_semantic_action<Subject> {};
0259 
0260     ///////////////////////////////////////////////////////////////////////////
0261     template <typename Subject, typename State, typename Attribute
0262         , typename Context, typename Iterator>
0263     struct handles_container<qi::state_switcher_context<Subject, State>
0264           , Attribute, Context, Iterator>
0265       : unary_handles_container<Subject, Attribute, Context, Iterator> {}; 
0266 }}}
0267 
0268 #endif