Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/spirit/home/qi/action/action.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*=============================================================================
0002     Copyright (c) 2001-2011 Joel de Guzman
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 #ifndef BOOST_SPIRIT_QI_ACTION_ACTION_HPP
0008 #define BOOST_SPIRIT_QI_ACTION_ACTION_HPP
0009 
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013 
0014 #include <boost/spirit/home/qi/meta_compiler.hpp>
0015 #include <boost/spirit/home/qi/parser.hpp>
0016 #include <boost/spirit/home/qi/detail/attributes.hpp>
0017 #include <boost/spirit/home/support/argument.hpp>
0018 #include <boost/spirit/home/support/context.hpp>
0019 #include <boost/spirit/home/support/unused.hpp>
0020 #include <boost/spirit/home/support/info.hpp>
0021 #include <boost/spirit/home/support/action_dispatch.hpp>
0022 #include <boost/spirit/home/support/handles_container.hpp>
0023 
0024 #include <boost/mpl/bool.hpp>
0025 #include <boost/mpl/if.hpp>
0026 #include <boost/type_traits/remove_const.hpp>
0027 #include <boost/type_traits/is_same.hpp>
0028 
0029 namespace boost { namespace spirit { namespace qi
0030 {
0031     BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _)
0032 
0033     template <typename Subject, typename Action>
0034     struct action : unary_parser<action<Subject, Action> >
0035     {
0036         typedef Subject subject_type;
0037         typedef Action action_type;
0038 
0039         template <typename Context, typename Iterator>
0040         struct attribute
0041           : traits::attribute_of<Subject, Context, Iterator>
0042         {};
0043 
0044         action(Subject const& subject_, Action f_)
0045           : subject(subject_), f(f_) {}
0046 
0047 #ifndef BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT
0048         template <typename Iterator, typename Context
0049           , typename Skipper, typename Attribute>
0050         bool parse(Iterator& first, Iterator const& last
0051           , Context& context, Skipper const& skipper
0052           , Attribute& attr_) const
0053         {
0054             typedef typename attribute<Context, Iterator>::type attr_type;
0055 
0056             // create an attribute if one is not supplied
0057             typedef traits::transform_attribute<
0058                 Attribute, attr_type, domain> transform;
0059 
0060             typename transform::type attr = transform::pre(attr_);
0061 
0062             Iterator save = first;
0063             if (subject.parse(first, last, context, skipper, attr))
0064             {
0065                 // call the function, passing the attribute, the context.
0066                 // The client can return false to fail parsing.
0067                 if (traits::action_dispatch<Subject>()(f, attr, context)) 
0068                 {
0069                     // Do up-stream transformation, this integrates the results
0070                     // back into the original attribute value, if appropriate.
0071                     transform::post(attr_, attr);
0072                     return true;
0073                 }
0074 
0075                 // reset iterators if semantic action failed the match
0076                 // retrospectively
0077                 first = save;
0078             }
0079             return false;
0080         }
0081 #else
0082         template <typename Iterator, typename Context
0083           , typename Skipper, typename Attribute>
0084         bool parse(Iterator& first, Iterator const& last
0085           , Context& context, Skipper const& skipper
0086           , Attribute& attr) const
0087         {
0088             Iterator save = first;
0089             if (subject.parse(first, last, context, skipper, attr)) // Use the attribute as-is
0090             {
0091                 // call the function, passing the attribute, the context.
0092                 // The client can return false to fail parsing.
0093                 if (traits::action_dispatch<Subject>()(f, attr, context))
0094                     return true;
0095 
0096                 // reset iterators if semantic action failed the match
0097                 // retrospectively
0098                 first = save;
0099             }
0100             return false;
0101         }
0102 
0103         template <typename Iterator, typename Context
0104           , typename Skipper>
0105         bool parse(Iterator& first, Iterator const& last
0106           , Context& context, Skipper const& skipper
0107           , unused_type) const
0108         {
0109             typedef typename attribute<Context, Iterator>::type attr_type;
0110 
0111             // synthesize the attribute since one is not supplied
0112             attr_type attr = attr_type();
0113 
0114             Iterator save = first;
0115             if (subject.parse(first, last, context, skipper, attr))
0116             {
0117                 // call the function, passing the attribute, the context.
0118                 // The client can return false to fail parsing.
0119                 if (traits::action_dispatch<Subject>()(f, attr, context))
0120                     return true;
0121 
0122                 // reset iterators if semantic action failed the match
0123                 // retrospectively
0124                 first = save;
0125             }
0126             return false;
0127         }
0128 #endif
0129 
0130         template <typename Context>
0131         info what(Context& context) const
0132         {
0133             // the action is transparent (does not add any info)
0134             return subject.what(context);
0135         }
0136 
0137         Subject subject;
0138         Action f;
0139     };
0140 }}}
0141 
0142 namespace boost { namespace spirit
0143 {
0144     // Qi action meta-compiler
0145     template <>
0146     struct make_component<qi::domain, tag::action>
0147     {
0148         template <typename Sig>
0149         struct result;
0150 
0151         template <typename This, typename Elements, typename Modifiers>
0152         struct result<This(Elements, Modifiers)>
0153         {
0154             typedef typename
0155                 remove_const<typename Elements::car_type>::type
0156             subject_type;
0157 
0158             typedef typename
0159                 remove_const<typename Elements::cdr_type::car_type>::type
0160             action_type;
0161 
0162             typedef qi::action<subject_type, action_type> type;
0163         };
0164 
0165         template <typename Elements>
0166         typename result<make_component(Elements, unused_type)>::type
0167         operator()(Elements const& elements, unused_type) const
0168         {
0169             typename result<make_component(Elements, unused_type)>::type
0170                 result(elements.car, elements.cdr.car);
0171             return result;
0172         }
0173     };
0174 }}
0175 
0176 namespace boost { namespace spirit { namespace traits
0177 {
0178     ///////////////////////////////////////////////////////////////////////////
0179     template <typename Subject, typename Action>
0180     struct has_semantic_action<qi::action<Subject, Action> >
0181       : mpl::true_ {};
0182 
0183     ///////////////////////////////////////////////////////////////////////////
0184     template <typename Subject, typename Action, typename Attribute
0185         , typename Context, typename Iterator>
0186     struct handles_container<qi::action<Subject, Action>, Attribute
0187         , Context, Iterator>
0188       : unary_handles_container<Subject, Attribute, Context, Iterator> {};
0189 }}}
0190 
0191 #endif