Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r61726 - in trunk/boost/spirit/home: karma/detail karma/operator support
From: hartmut.kaiser_at_[hidden]
Date: 2010-05-01 23:06:32


Author: hkaiser
Date: 2010-05-01 23:06:31 EDT (Sat, 01 May 2010)
New Revision: 61726
URL: http://svn.boost.org/trac/boost/changeset/61726

Log:
Spirit: introduced new cutomization point for karma alternatives (variant_which) and extended strict mode to alternatives
Text files modified:
   trunk/boost/spirit/home/karma/detail/alternative_function.hpp | 68 +++++++++++++++++++++++++++++++++++----
   trunk/boost/spirit/home/karma/operator/alternative.hpp | 50 ++++++++++++++++++++++++++--
   trunk/boost/spirit/home/support/attributes.hpp | 20 +++++++++++
   3 files changed, 125 insertions(+), 13 deletions(-)

Modified: trunk/boost/spirit/home/karma/detail/alternative_function.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/alternative_function.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/alternative_function.hpp 2010-05-01 23:06:31 EDT (Sat, 01 May 2010)
@@ -38,8 +38,9 @@
         template <typename OutputIterator, typename Context, typename Delimiter>
         static bool
         call(Component const&, OutputIterator&, Context&, Delimiter const&
- , Attribute const&)
+ , Attribute const&, bool& failed)
         {
+ failed = true;
             return false;
         }
     };
@@ -50,7 +51,7 @@
         template <typename OutputIterator, typename Context, typename Delimiter>
         static bool
         call(Component const& component, OutputIterator& sink, Context& ctx
- , Delimiter const& d, unused_type)
+ , Delimiter const& d, unused_type, bool&)
         {
 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
             component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
@@ -82,7 +83,7 @@
         template <typename OutputIterator, typename Context, typename Delimiter>
         static bool
         call(Component const& component, OutputIterator& sink
- , Context& ctx, Delimiter const& d, Attribute const& attr)
+ , Context& ctx, Delimiter const& d, Attribute const& attr, bool&)
         {
 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
             component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
@@ -122,7 +123,7 @@
             // expectations
             typename traits::optional_attribute<Attribute>::type attr_ =
                 traits::optional_value(attr);
- if (!component_type::is_compatible(attr_.which()))
+ if (!component_type::is_compatible(spirit::traits::which(attr_)))
                 return false;
 
             // returns true if any of the generators succeed
@@ -137,11 +138,11 @@
     // expression
     ///////////////////////////////////////////////////////////////////////////
     template <typename OutputIterator, typename Context, typename Delimiter,
- typename Attribute>
+ typename Attribute, typename Strict>
     struct alternative_generate_function
     {
         alternative_generate_function(OutputIterator& sink_, Context& ctx_
- , Delimiter const& d, Attribute const& attr_)
+ , Delimiter const& d, Attribute const& attr_)
           : sink(sink_), ctx(ctx_), delim(d), attr(attr_) {}
 
         template <typename Component>
@@ -158,9 +159,10 @@
             // component fails
             detail::enable_buffering<OutputIterator> buffering(sink);
             bool r = false;
+ bool failed = false; // will be ignored
             {
                 detail::disable_counting<OutputIterator> nocounting(sink);
- r = generate::call(component, sink, ctx, delim, attr);
+ r = generate::call(component, sink, ctx, delim, attr, failed);
             }
             if (r)
                 buffering.buffer_copy();
@@ -178,7 +180,8 @@
                 buffer_directive<Component>, Attribute, expected_type>
             generate;
 
- return generate::call(component, sink, ctx, delim, attr);
+ bool failed = false; // will be ignored
+ return generate::call(component, sink, ctx, delim, attr, failed);
         }
 
         OutputIterator& sink;
@@ -191,6 +194,55 @@
         alternative_generate_function& operator= (alternative_generate_function const&);
     };
 
+ // specialization for strict alternatives
+ template <typename OutputIterator, typename Context, typename Delimiter,
+ typename Attribute>
+ struct alternative_generate_function<
+ OutputIterator, Context, Delimiter, Attribute, mpl::true_>
+ {
+ alternative_generate_function(OutputIterator& sink_, Context& ctx_
+ , Delimiter const& d, Attribute const& attr_)
+ : sink(sink_), ctx(ctx_), delim(d), attr(attr_), failed(false) {}
+
+ template <typename Component>
+ bool operator()(Component const& component)
+ {
+ typedef
+ typename traits::attribute_of<Component, Context>::type
+ expected_type;
+ typedef
+ alternative_generate<Component, Attribute, expected_type>
+ generate;
+
+ if (failed)
+ return false; // give up when already failed
+
+ // wrap the given output iterator avoid output as long as one
+ // component fails
+ detail::enable_buffering<OutputIterator> buffering(sink);
+ bool r = false;
+ {
+ detail::disable_counting<OutputIterator> nocounting(sink);
+ r = generate::call(component, sink, ctx, delim, attr, failed);
+ }
+ if (r && !failed)
+ {
+ buffering.buffer_copy();
+ return true;
+ }
+ return false;
+ }
+
+ OutputIterator& sink;
+ Context& ctx;
+ Delimiter const& delim;
+ Attribute const& attr;
+ bool failed;
+
+ private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ alternative_generate_function& operator= (alternative_generate_function const&);
+ };
 }}}}
 
 #endif

Modified: trunk/boost/spirit/home/karma/operator/alternative.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/alternative.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/alternative.hpp 2010-05-01 23:06:31 EDT (Sat, 01 May 2010)
@@ -12,6 +12,7 @@
 #endif
 
 #include <boost/spirit/home/karma/detail/alternative_function.hpp>
+#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
 #include <boost/spirit/home/karma/domain.hpp>
 #include <boost/spirit/home/karma/generator.hpp>
 #include <boost/spirit/home/karma/meta_compiler.hpp>
@@ -75,8 +76,8 @@
 
 namespace boost { namespace spirit { namespace karma
 {
- template <typename Elements>
- struct alternative : nary_generator<alternative<Elements> >
+ template <typename Elements, typename Strict, typename Derived>
+ struct base_alternative : nary_generator<Derived>
     {
         typedef typename traits::alternative_properties<Elements>::type
             properties;
@@ -97,7 +98,7 @@
             typedef typename traits::build_variant<all_attributes>::type type;
         };
 
- alternative(Elements const& elements)
+ base_alternative(Elements const& elements)
           : elements(elements) {}
 
         template <
@@ -107,7 +108,7 @@
           , Delimiter const& d, Attribute const& attr) const
         {
             typedef detail::alternative_generate_function<
- OutputIterator, Context, Delimiter, Attribute
+ OutputIterator, Context, Delimiter, Attribute, Strict
> functor;
 
             // f return true if *any* of the parser succeeds
@@ -127,12 +128,48 @@
         Elements elements;
     };
 
+ template <typename Elements>
+ struct alternative
+ : base_alternative<Elements, mpl::false_, alternative<Elements> >
+ {
+ typedef base_alternative<Elements, mpl::false_, alternative>
+ base_alternative_;
+
+ alternative(Elements const& elements)
+ : base_alternative_(elements) {}
+ };
+
+ template <typename Elements>
+ struct strict_alternative
+ : base_alternative<Elements, mpl::true_, strict_alternative<Elements> >
+ {
+ typedef base_alternative<Elements, mpl::true_, strict_alternative>
+ base_alternative_;
+
+ strict_alternative(Elements const& elements)
+ : base_alternative_(elements) {}
+ };
+
     ///////////////////////////////////////////////////////////////////////////
     // Generator generators: make_xxx function (objects)
     ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ template <typename Elements, bool strict_mode = false>
+ struct make_alternative
+ : make_nary_composite<Elements, alternative>
+ {};
+
+ template <typename Elements>
+ struct make_alternative<Elements, true>
+ : make_nary_composite<Elements, strict_alternative>
+ {};
+ }
+
     template <typename Elements, typename Modifiers>
     struct make_composite<proto::tag::bitwise_or, Elements, Modifiers>
- : make_nary_composite<Elements, alternative>
+ : detail::make_alternative<Elements
+ , detail::get_stricttag<Modifiers>::value>
     {};
 
 }}}
@@ -143,6 +180,9 @@
     struct has_semantic_action<karma::alternative<Elements> >
       : nary_has_semantic_action<Elements> {};
 
+ template <typename Elements>
+ struct has_semantic_action<karma::strict_alternative<Elements> >
+ : nary_has_semantic_action<Elements> {};
 }}}
 
 #endif

Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp (original)
+++ trunk/boost/spirit/home/support/attributes.hpp 2010-05-01 23:06:31 EDT (Sat, 01 May 2010)
@@ -186,6 +186,26 @@
       : mpl::false_ {};
 
     ///////////////////////////////////////////////////////////////////////////
+ // return the type currently stored in the given variant
+ template <typename T, typename Enable = void>
+ struct variant_which;
+
+ template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+ struct variant_which<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+ {
+ static int call(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& v)
+ {
+ return v.which();
+ }
+ };
+
+ template <typename T>
+ int which(T const& v)
+ {
+ return variant_which<T>::call(v);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
     template <typename T, typename Domain>
     struct not_is_optional
       : mpl::true_


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk