Chris@16: /*============================================================================= Chris@16: Copyright (c) 2001-2011 Hartmut Kaiser 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_ALTERNATIVE_FUNCTION_APRIL_23_2007_1046AM) Chris@16: #define SPIRIT_ALTERNATIVE_FUNCTION_APRIL_23_2007_1046AM 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: Chris@16: namespace boost { namespace spirit { namespace qi { namespace detail Chris@16: { Chris@16: template Chris@16: struct find_substitute Chris@16: { Chris@16: // Get the typr from the variant that can be a substitute for Expected. Chris@16: // If none is found, just return Expected Chris@16: Chris@16: typedef Variant variant_type; Chris@16: typedef typename variant_type::types types; Chris@16: typedef typename mpl::end::type end; Chris@16: Chris@16: typedef typename Chris@16: mpl::find_if >::type Chris@16: iter_1; Chris@16: Chris@16: typedef typename Chris@16: mpl::eval_if< Chris@16: is_same, Chris@16: mpl::find_if >, Chris@16: mpl::identity Chris@16: >::type Chris@16: iter; Chris@16: Chris@16: typedef typename Chris@16: mpl::eval_if< Chris@16: is_same, Chris@16: mpl::identity, Chris@16: mpl::deref Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct alternative_function Chris@16: { Chris@16: alternative_function( Chris@16: Iterator& first_, Iterator const& last_, Context& context_, Chris@16: Skipper const& skipper_, Attribute& attr_) Chris@16: : first(first_), last(last_), context(context_), skipper(skipper_), Chris@16: attr(attr_) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: bool call(Component const& component, mpl::true_) const Chris@16: { Chris@16: // if Attribute is not a variant, then pass it as-is Chris@16: return component.parse(first, last, context, skipper, attr); Chris@16: } Chris@16: Chris@16: template Chris@16: bool call_optional_or_variant(Component const& component, mpl::true_) const Chris@16: { Chris@16: // If Attribute is an optional, then create an attribute for the Component Chris@16: // with the type optional::value_type. If the expected attribute is unused type, Chris@16: // use it instead. Chris@16: typedef typename Chris@16: traits::attribute_of::type Chris@16: expected_type; Chris@16: Chris@16: typename mpl::if_< Chris@16: is_same, Chris@16: unused_type, Chris@16: typename Attribute::value_type>::type Chris@16: val; Chris@16: Chris@16: if (component.parse(first, last, context, skipper, val)) Chris@16: { Chris@16: traits::assign_to(val, attr); Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: template Chris@16: bool call_variant(Component const& component, mpl::false_) const Chris@16: { Chris@16: // If Attribute is a variant, then search the variant types for a Chris@16: // suitable substitute type. Chris@16: Chris@16: typename Chris@16: find_substitute::type Chris@16: >::type Chris@16: val; Chris@16: Chris@16: if (component.parse(first, last, context, skipper, val)) Chris@16: { Chris@16: traits::assign_to(val, attr); Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: template Chris@16: bool call_variant(Component const& component, mpl::true_) const Chris@16: { Chris@16: // If Attribute is a variant and the expected attribute is Chris@16: // the same type (pass the variant as-is). Chris@16: Chris@16: return component.parse(first, last, context, skipper, attr); Chris@16: } Chris@16: Chris@16: template Chris@16: bool call_optional_or_variant(Component const& component, mpl::false_) const Chris@16: { Chris@16: // Attribute is a variant... Chris@16: Chris@16: typedef typename Chris@16: traits::attribute_of::type Chris@16: expected; Chris@16: return call_variant(component, Chris@16: is_same()); Chris@16: } Chris@16: Chris@16: template Chris@16: bool call(Component const& component, mpl::false_) const Chris@16: { Chris@16: return call_optional_or_variant( Chris@16: component, spirit::traits::not_is_variant()); Chris@16: } Chris@16: Chris@16: template Chris@16: bool call_unused(Component const& component, mpl::true_) const Chris@16: { Chris@16: // return true if the parser succeeds Chris@16: return call(component, Chris@16: mpl::and_< Chris@16: spirit::traits::not_is_variant, Chris@16: spirit::traits::not_is_optional Chris@16: >()); Chris@16: } Chris@16: Chris@16: template Chris@16: bool call_unused(Component const& component, mpl::false_) const Chris@16: { Chris@16: return component.parse(first, last, context, skipper, unused); Chris@16: } Chris@16: Chris@16: template Chris@16: bool operator()(Component const& component) const Chris@16: { Chris@16: // return true if the parser succeeds Chris@16: typedef typename traits::not_is_unused< Chris@16: typename traits::attribute_of::type Chris@16: >::type predicate; Chris@16: Chris@16: return call_unused(component, predicate()); Chris@16: } Chris@16: Chris@16: Iterator& first; Chris@16: Iterator const& last; Chris@16: Context& context; Chris@16: Skipper const& skipper; Chris@16: Attribute& attr; Chris@16: Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: alternative_function& operator= (alternative_function const&); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct alternative_function Chris@16: { Chris@16: alternative_function( Chris@16: Iterator& first_, Iterator const& last_, Context& context_, Chris@16: Skipper const& skipper_, unused_type) Chris@16: : first(first_), last(last_), context(context_), skipper(skipper_) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@101: bool operator()(Component const& component) const Chris@16: { Chris@16: // return true if the parser succeeds Chris@16: return component.parse(first, last, context, skipper, Chris@16: unused); Chris@16: } Chris@16: Chris@16: Iterator& first; Chris@16: Iterator const& last; Chris@16: Context& context; Chris@16: Skipper const& skipper; Chris@16: Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: alternative_function& operator= (alternative_function const&); Chris@16: }; Chris@16: Chris@16: }}}} Chris@16: Chris@16: #endif