/*============================================================================= Copyright (c) 2001-2011 Joel de Guzman Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #if !defined(SPIRIT_ACTION_JANUARY_07_2007_1128AM) #define SPIRIT_ACTION_JANUARY_07_2007_1128AM #if defined(_MSC_VER) #pragma once #endif #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace spirit { namespace qi { BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _) template struct action : unary_parser > { typedef Subject subject_type; typedef Action action_type; template struct attribute : traits::attribute_of {}; action(Subject const& subject, Action f) : subject(subject), f(f) {} #ifndef BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT template bool parse(Iterator& first, Iterator const& last , Context& context, Skipper const& skipper , Attribute& attr_) const { typedef typename attribute::type attr_type; typedef traits::make_attribute make_attribute; // create an attribute if one is not supplied typedef traits::transform_attribute< typename make_attribute::type, attr_type, domain> transform; typename make_attribute::type made_attr = make_attribute::call(attr_); typename transform::type attr = transform::pre(made_attr); Iterator save = first; if (subject.parse(first, last, context, skipper, attr)) { // call the function, passing the attribute, the context. // The client can return false to fail parsing. if (traits::action_dispatch()(f, attr, context)) { // Do up-stream transformation, this integrates the results // back into the original attribute value, if appropriate. traits::post_transform(attr_, attr); return true; } // reset iterators if semantic action failed the match // retrospectively first = save; } return false; } #else template bool parse(Iterator& first, Iterator const& last , Context& context, Skipper const& skipper , Attribute& attr) const { Iterator save = first; if (subject.parse(first, last, context, skipper, attr)) // Use the attribute as-is { // call the function, passing the attribute, the context. // The client can return false to fail parsing. if (traits::action_dispatch()(f, attr, context)) return true; // reset iterators if semantic action failed the match // retrospectively first = save; } return false; } template bool parse(Iterator& first, Iterator const& last , Context& context, Skipper const& skipper , unused_type) const { typedef typename attribute::type attr_type; typedef traits::make_attribute make_attribute; // synthesize the attribute since one is not supplied typedef traits::transform_attribute< typename make_attribute::type, attr_type, domain> transform; typename make_attribute::type made_attr = make_attribute::call(unused_type()); typename transform::type attr = transform::pre(made_attr); Iterator save = first; if (subject.parse(first, last, context, skipper, attr)) { // call the function, passing the attribute, the context. // The client can return false to fail parsing. if (traits::action_dispatch()(f, attr, context)) return true; // reset iterators if semantic action failed the match // retrospectively first = save; } return false; } #endif template info what(Context& context) const { // the action is transparent (does not add any info) return subject.what(context); } Subject subject; Action f; private: // silence MSVC warning C4512: assignment operator could not be generated action& operator= (action const&); }; }}} namespace boost { namespace spirit { // Qi action meta-compiler template <> struct make_component { template struct result; template struct result { typedef typename remove_const::type subject_type; typedef typename remove_const::type action_type; typedef qi::action type; }; template typename result::type operator()(Elements const& elements, unused_type) const { typename result::type result(elements.car, elements.cdr.car); return result; } }; }} namespace boost { namespace spirit { namespace traits { /////////////////////////////////////////////////////////////////////////// template struct has_semantic_action > : mpl::true_ {}; /////////////////////////////////////////////////////////////////////////// template struct handles_container, Attribute , Context, Iterator> : unary_handles_container {}; }}} #endif