File indexing completed on 2025-01-31 10:02:18
0001
0002
0003
0004
0005
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
0029
0030
0031
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
0038 template <>
0039 struct use_lazy_terminal<
0040 qi::domain, tag::set_state, 1
0041 > : mpl::true_ {};
0042
0043
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
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
0083
0084
0085
0086 BOOST_ASSERT(std::size_t(~0) != state);
0087 return it.set_state(state);
0088 }
0089 }
0090
0091
0092
0093
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& , Skipper const& skipper
0117 , Attribute& ) const
0118 {
0119 qi::skip_over(first, last, skipper);
0120
0121
0122 detail::set_lexer_state(first, state.c_str());
0123 return true;
0124 }
0125
0126 template <typename Context>
0127 info what(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)
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
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
0167
0168
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
0191
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);
0204
0205
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
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