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