|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r61491 - in trunk: boost/spirit/home/karma boost/spirit/home/karma/detail boost/spirit/home/karma/directive boost/spirit/home/karma/operator boost/spirit/home/support boost/spirit/include libs/spirit/test/karma
From: hartmut.kaiser_at_[hidden]
Date: 2010-04-22 16:25:12
Author: hkaiser
Date: 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
New Revision: 61491
URL: http://svn.boost.org/trac/boost/changeset/61491
Log:
Spirit: added strict mode to Karma, new directives strict[] and relaxed[]. No docs yet
Added:
trunk/boost/spirit/home/karma/detail/get_stricttag.hpp (contents, props changed)
trunk/boost/spirit/home/karma/directive/strict_relaxed.hpp (contents, props changed)
trunk/boost/spirit/include/karma_strict_relaxed.hpp (contents, props changed)
Text files modified:
trunk/boost/spirit/home/karma/detail/get_casetag.hpp | 3 +
trunk/boost/spirit/home/karma/directive.hpp | 10 ++++-
trunk/boost/spirit/home/karma/directive/repeat.hpp | 76 +++++++++++++++++++++++++++++++++-----
trunk/boost/spirit/home/karma/operator/kleene.hpp | 57 +++++++++++++++++++++++-----
trunk/boost/spirit/home/karma/operator/list.hpp | 71 ++++++++++++++++++++++++++++-------
trunk/boost/spirit/home/karma/operator/plus.hpp | 54 +++++++++++++++++++++++----
trunk/boost/spirit/home/karma/operator/sequence.hpp | 79 ++++++++++++++++++++++++++++++++++++---
trunk/boost/spirit/home/support/common_terminals.hpp | 2 +
trunk/libs/spirit/test/karma/kleene.cpp | 16 ++++++++
trunk/libs/spirit/test/karma/list.cpp | 17 ++++++++
trunk/libs/spirit/test/karma/plus.cpp | 18 ++++++++
trunk/libs/spirit/test/karma/repeat.cpp | 29 ++++++++++++++
trunk/libs/spirit/test/karma/sequence.cpp | 34 +++++++++++++++++
13 files changed, 413 insertions(+), 53 deletions(-)
Modified: trunk/boost/spirit/home/karma/detail/get_casetag.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/get_casetag.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/get_casetag.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -12,6 +12,8 @@
#endif
#include <boost/mpl/identity.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/spirit/home/support/common_terminals.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
@@ -22,7 +24,6 @@
struct get_casetag<Modifiers, true>
: mpl::if_<has_modifier<Modifiers, tag::char_code_base<tag::lower> >
, tag::lower, tag::upper> {};
-
}}}}
#endif
Added: trunk/boost/spirit/home/karma/detail/get_stricttag.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/karma/detail/get_stricttag.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -0,0 +1,33 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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(BOOST_SPIRIT_KARMA_GET_STRICTTAG_APR_22_2010_1007AM)
+#define BOOST_SPIRIT_KARMA_GET_STRICTTAG_APR_22_2010_1007AM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/spirit/home/support/common_terminals.hpp>
+
+namespace boost { namespace spirit { namespace karma { namespace detail
+{
+ // the default mode for Karma is 'relaxed'
+ template <
+ typename Modifiers
+ , typename StrictModifier = typename mpl::or_<
+ has_modifier<Modifiers, tag::strict>
+ , has_modifier<Modifiers, tag::relaxed> >::type>
+ struct get_stricttag : mpl::false_ {};
+
+ // strict mode is enforced only when tag::strict is on the modifiers list
+ template <typename Modifiers>
+ struct get_stricttag<Modifiers, mpl::true_>
+ : has_modifier<Modifiers, tag::strict> {};
+}}}}
+
+#endif
Modified: trunk/boost/spirit/home/karma/directive.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive.hpp (original)
+++ trunk/boost/spirit/home/karma/directive.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -48,8 +48,8 @@
#include <boost/spirit/home/karma/directive/repeat.hpp>
///////////////////////////////////////////////////////////////////////////////
-// omit directive
-// omit[...]
+// omit and skip[] directives
+// omit[...], skip[...]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/omit.hpp>
@@ -59,4 +59,10 @@
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/buffer.hpp>
+///////////////////////////////////////////////////////////////////////////////
+// strict and relaxed directives
+// strict[...], relaxed[...]
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/home/karma/directive/strict_relaxed.hpp>
+
#endif
Modified: trunk/boost/spirit/home/karma/directive/repeat.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/repeat.hpp (original)
+++ trunk/boost/spirit/home/karma/directive/repeat.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -12,6 +12,8 @@
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
+#include <boost/spirit/home/karma/detail/output_iterator.hpp>
+#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/operator/kleene.hpp>
@@ -61,7 +63,6 @@
, tag::repeat
, 2 // arity
> : mpl::true_ {};
-
}}
namespace boost { namespace spirit { namespace karma
@@ -132,9 +133,9 @@
};
///////////////////////////////////////////////////////////////////////////
- template <typename Subject, typename LoopIter>
- struct repeat_generator
- : unary_generator<repeat_generator<Subject, LoopIter> >
+ template <typename Subject, typename LoopIter, typename Strict
+ , typename Derived>
+ struct base_repeat_generator : unary_generator<Derived>
{
private:
// iterate over the given container until its exhausted or the embedded
@@ -151,6 +152,8 @@
{
if (subject.generate(sink, ctx, d, traits::deref(it)))
return true;
+ if (Strict::value)
+ return false;
traits::next(it);
}
return false;
@@ -183,7 +186,7 @@
>
{};
- repeat_generator(Subject const& subject, LoopIter const& iter)
+ base_repeat_generator(Subject const& subject, LoopIter const& iter)
: subject(subject), iter(iter) {}
template <typename OutputIterator, typename Context, typename Delimiter
@@ -230,14 +233,49 @@
LoopIter iter;
};
+ template <typename Subject, typename LoopIter>
+ struct repeat_generator
+ : base_repeat_generator<
+ Subject, LoopIter, mpl::false_
+ , repeat_generator<Subject, LoopIter> >
+ {
+ typedef base_repeat_generator<
+ Subject, LoopIter, mpl::false_, repeat_generator
+ > base_repeat_generator_;
+
+ repeat_generator(Subject const& subject, LoopIter const& iter)
+ : base_repeat_generator_(subject, iter)
+ {}
+ };
+
+ template <typename Subject, typename LoopIter>
+ struct strict_repeat_generator
+ : base_repeat_generator<
+ Subject, LoopIter, mpl::true_
+ , strict_repeat_generator<Subject, LoopIter> >
+ {
+ typedef base_repeat_generator<
+ Subject, LoopIter, mpl::true_, strict_repeat_generator
+ > base_repeat_generator_;
+
+ strict_repeat_generator(Subject const& subject, LoopIter const& iter)
+ : base_repeat_generator_(subject, iter)
+ {}
+ };
+
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Modifiers>
struct make_directive<tag::repeat, Subject, Modifiers>
{
- typedef kleene<Subject> result_type;
- result_type operator()(unused_type, Subject const& subject, unused_type) const
+ typedef typename mpl::if_<
+ detail::get_stricttag<Modifiers>
+ , strict_kleene<Subject>, kleene<Subject>
+ >::type result_type;
+
+ result_type operator()(unused_type, Subject const& subject
+ , unused_type) const
{
return result_type(subject);
}
@@ -248,7 +286,12 @@
terminal_ex<tag::repeat, fusion::vector1<T> >, Subject, Modifiers>
{
typedef exact_iterator<T> iterator_type;
- typedef repeat_generator<Subject, iterator_type> result_type;
+
+ typedef typename mpl::if_<
+ detail::get_stricttag<Modifiers>
+ , strict_repeat_generator<Subject, iterator_type>
+ , repeat_generator<Subject, iterator_type>
+ >::type result_type;
template <typename Terminal>
result_type operator()(
@@ -263,7 +306,12 @@
terminal_ex<tag::repeat, fusion::vector2<T, T> >, Subject, Modifiers>
{
typedef finite_iterator<T> iterator_type;
- typedef repeat_generator<Subject, iterator_type> result_type;
+
+ typedef typename mpl::if_<
+ detail::get_stricttag<Modifiers>
+ , strict_repeat_generator<Subject, iterator_type>
+ , repeat_generator<Subject, iterator_type>
+ >::type result_type;
template <typename Terminal>
result_type operator()(
@@ -284,7 +332,12 @@
, fusion::vector2<T, inf_type> >, Subject, Modifiers>
{
typedef infinite_iterator<T> iterator_type;
- typedef repeat_generator<Subject, iterator_type> result_type;
+
+ typedef typename mpl::if_<
+ detail::get_stricttag<Modifiers>
+ , strict_repeat_generator<Subject, iterator_type>
+ , repeat_generator<Subject, iterator_type>
+ >::type result_type;
template <typename Terminal>
result_type operator()(
@@ -302,6 +355,9 @@
struct has_semantic_action<karma::repeat_generator<Subject, LoopIter> >
: unary_has_semantic_action<Subject> {};
+ template <typename Subject, typename LoopIter>
+ struct has_semantic_action<karma::strict_repeat_generator<Subject, LoopIter> >
+ : unary_has_semantic_action<Subject> {};
}}}
#endif
Added: trunk/boost/spirit/home/karma/directive/strict_relaxed.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/karma/directive/strict_relaxed.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -0,0 +1,76 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// 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_STRICT_RELAXED_APR_22_2010_0959AM)
+#define SPIRIT_STRICT_RELAXED_APR_22_2010_0959AM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/support/common_terminals.hpp>
+#include <boost/spirit/home/support/modify.hpp>
+#include <boost/spirit/home/karma/domain.hpp>
+#include <boost/spirit/home/karma/meta_compiler.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_directive<karma::domain, tag::strict> // enables strict[]
+ : mpl::true_ {};
+
+ template <>
+ struct use_directive<karma::domain, tag::relaxed> // enables relaxed[]
+ : mpl::true_ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct is_modifier_directive<karma::domain, tag::strict>
+ : mpl::true_ {};
+
+ template <>
+ struct is_modifier_directive<karma::domain, tag::relaxed>
+ : mpl::true_ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Don't add tag::strict or tag::relaxed if there is already one of those
+ // in the modifier list
+ template <typename Current>
+ struct compound_modifier<Current, tag::strict
+ , typename enable_if<has_modifier<Current, tag::relaxed> >::type>
+ : Current
+ {
+ compound_modifier()
+ : Current() {}
+
+ compound_modifier(Current const& current, tag::strict const&)
+ : Current(current) {}
+ };
+
+ template <typename Current>
+ struct compound_modifier<Current, tag::relaxed
+ , typename enable_if<has_modifier<Current, tag::strict> >::type>
+ : Current
+ {
+ compound_modifier()
+ : Current() {}
+
+ compound_modifier(Current const& current, tag::relaxed const&)
+ : Current(current) {}
+ };
+
+ namespace karma
+ {
+ using boost::spirit::strict;
+ using boost::spirit::strict_type;
+ using boost::spirit::relaxed;
+ using boost::spirit::relaxed_type;
+ }
+}}
+
+#endif
Modified: trunk/boost/spirit/home/karma/operator/kleene.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/kleene.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/kleene.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -15,6 +15,7 @@
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
+#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
@@ -30,14 +31,13 @@
template <>
struct use_operator<karma::domain, proto::tag::dereference> // enables *g
: mpl::true_ {};
-
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
- template <typename Subject>
- struct kleene : unary_generator<kleene<Subject> >
+ template <typename Subject, typename Strict, typename Derived>
+ struct base_kleene : unary_generator<Derived>
{
private:
template <
@@ -49,8 +49,8 @@
// Ignore return value, failing subject generators are just
// skipped. This allows to selectively generate items in the
// provided attribute.
- subject.generate(sink, ctx, d, attr);
- return true;
+ bool r = subject.generate(sink, ctx, d, attr);
+ return !Strict::value || r;
}
template <typename OutputIterator, typename Context, typename Delimiter>
@@ -77,7 +77,7 @@
>
{};
- kleene(Subject const& subject)
+ base_kleene(Subject const& subject)
: subject(subject) {}
template <
@@ -112,14 +112,48 @@
Subject subject;
};
+ template <typename Subject>
+ struct kleene
+ : base_kleene<Subject, mpl::false_, kleene<Subject> >
+ {
+ typedef base_kleene<Subject, mpl::false_, kleene> base_kleene_;
+
+ kleene(Subject const& subject)
+ : base_kleene_(subject)
+ {}
+ };
+
+ template <typename Subject>
+ struct strict_kleene
+ : base_kleene<Subject, mpl::true_, strict_kleene<Subject> >
+ {
+ typedef base_kleene<Subject, mpl::true_, strict_kleene> base_kleene_;
+
+ strict_kleene(Subject const& subject)
+ : base_kleene_(subject)
+ {}
+ };
+
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
- template <typename Elements, typename Modifiers>
- struct make_composite<proto::tag::dereference, Elements, Modifiers>
- : make_unary_composite<Elements, kleene>
- {};
+ namespace detail
+ {
+ template <typename Subject, bool strict_mode = false>
+ struct make_kleene
+ : make_unary_composite<Subject, kleene>
+ {};
+ template <typename Subject>
+ struct make_kleene<Subject, true>
+ : make_unary_composite<Subject, strict_kleene>
+ {};
+ }
+
+ template <typename Subject, typename Modifiers>
+ struct make_composite<proto::tag::dereference, Subject, Modifiers>
+ : detail::make_kleene<Subject, detail::get_stricttag<Modifiers>::value>
+ {};
}}}
namespace boost { namespace spirit { namespace traits
@@ -128,6 +162,9 @@
struct has_semantic_action<karma::kleene<Subject> >
: unary_has_semantic_action<Subject> {};
+ template <typename Subject>
+ struct has_semantic_action<karma::strict_kleene<Subject> >
+ : unary_has_semantic_action<Subject> {};
}}}
#endif
Modified: trunk/boost/spirit/home/karma/operator/list.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/list.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/list.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -15,6 +15,7 @@
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
+#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
@@ -28,14 +29,13 @@
template <>
struct use_operator<karma::domain, proto::tag::modulus> // enables g % d
: mpl::true_ {};
-
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
- template <typename Left, typename Right>
- struct list : binary_generator<list<Left, Right> >
+ template <typename Left, typename Right, typename Strict, typename Derived>
+ struct base_list : binary_generator<Derived>
{
private:
// iterate over the given container until its exhausted or the embedded
@@ -46,13 +46,19 @@
bool generate_left(OutputIterator& sink, Context& ctx
, Delimiter const& d, Iterator& it, Iterator& end, Attribute const&) const
{
- // Failing subject generators are just skipped. This allows to
- // selectively generate items in the provided attribute.
- while (!traits::compare(it, end))
- {
- if (left.generate(sink, ctx, d, traits::deref(it)))
- return true;
- traits::next(it);
+ if (Strict::value) {
+ if (!traits::compare(it, end))
+ return left.generate(sink, ctx, d, traits::deref(it));
+ }
+ else {
+ // Failing subject generators are just skipped. This allows to
+ // selectively generate items in the provided attribute.
+ while (!traits::compare(it, end))
+ {
+ if (left.generate(sink, ctx, d, traits::deref(it)))
+ return true;
+ traits::next(it);
+ }
}
return false;
}
@@ -89,7 +95,7 @@
typename traits::attribute_of<Left, Context, Iterator>::type>
{};
- list(Left const& left, Right const& right)
+ base_list(Left const& left, Right const& right)
: left(left), right(right)
{}
@@ -139,14 +145,46 @@
Right right;
};
+ template <typename Left, typename Right>
+ struct list
+ : base_list<Left, Right, mpl::false_, list<Left, Right> >
+ {
+ typedef base_list<Left, Right, mpl::false_, list> base_list_;
+
+ list(Left const& left, Right const& right)
+ : base_list_(left, right) {}
+ };
+
+ template <typename Left, typename Right>
+ struct strict_list
+ : base_list<Left, Right, mpl::true_, strict_list<Left, Right> >
+ {
+ typedef base_list<Left, Right, mpl::true_, strict_list> base_list_;
+
+ strict_list (Left const& left, Right const& right)
+ : base_list_(left, right) {}
+ };
+
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
- template <typename Elements, typename Modifiers>
- struct make_composite<proto::tag::modulus, Elements, Modifiers>
- : make_binary_composite<Elements, list>
- {};
+ namespace detail
+ {
+ template <typename Subject, bool strict_mode = false>
+ struct make_list
+ : make_binary_composite<Subject, list>
+ {};
+
+ template <typename Subject>
+ struct make_list<Subject, true>
+ : make_binary_composite<Subject, strict_list>
+ {};
+ }
+ template <typename Subject, typename Modifiers>
+ struct make_composite<proto::tag::modulus, Subject, Modifiers>
+ : detail::make_list<Subject, detail::get_stricttag<Modifiers>::value>
+ {};
}}}
namespace boost { namespace spirit { namespace traits
@@ -155,6 +193,9 @@
struct has_semantic_action<karma::list<Left, Right> >
: binary_has_semantic_action<Left, Right> {};
+ template <typename Left, typename Right>
+ struct has_semantic_action<karma::strict_list<Left, Right> >
+ : binary_has_semantic_action<Left, Right> {};
}}}
#endif
Modified: trunk/boost/spirit/home/karma/operator/plus.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/plus.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/plus.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -15,6 +15,7 @@
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
+#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
@@ -30,14 +31,13 @@
template <>
struct use_operator<karma::domain, proto::tag::unary_plus> // enables +g
: mpl::true_ {};
-
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
- template <typename Subject>
- struct plus : unary_generator<plus<Subject> >
+ template <typename Subject, typename Strict, typename Derived>
+ struct base_plus : unary_generator<Derived>
{
private:
template <
@@ -49,9 +49,11 @@
// Ignore return value, failing subject generators are just
// skipped. This allows to selectively generate items in the
// provided attribute.
- if (subject.generate(sink, ctx, d, attr))
+ if (subject.generate(sink, ctx, d, attr)) {
result = true;
- return true;
+ return true;
+ }
+ return !Strict::value;
}
template <typename OutputIterator, typename Context, typename Delimiter>
@@ -82,7 +84,7 @@
>
{};
- plus(Subject const& subject)
+ base_plus(Subject const& subject)
: subject(subject) {}
template <
@@ -123,15 +125,48 @@
Subject subject;
};
+ template <typename Subject>
+ struct plus
+ : base_plus<Subject, mpl::false_, plus<Subject> >
+ {
+ typedef base_plus<Subject, mpl::false_, plus> base_plus;
+
+ plus(Subject const& subject)
+ : base_plus(subject)
+ {}
+ };
+
+ template <typename Subject>
+ struct strict_plus
+ : base_plus<Subject, mpl::true_, strict_plus<Subject> >
+ {
+ typedef base_plus<Subject, mpl::true_, strict_plus> base_plus;
+
+ strict_plus(Subject const& subject)
+ : base_plus(subject)
+ {}
+ };
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ template <typename Elements, bool strict_mode = false>
+ struct make_plus
+ : make_unary_composite<Elements, plus>
+ {};
+
+ template <typename Elements>
+ struct make_plus<Elements, true>
+ : make_unary_composite<Elements, strict_plus>
+ {};
+ }
+
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::unary_plus, Elements, Modifiers>
- : make_unary_composite<Elements, plus>
+ : detail::make_plus<Elements, detail::get_stricttag<Modifiers>::value>
{};
-
}}}
namespace boost { namespace spirit { namespace traits
@@ -140,6 +175,9 @@
struct has_semantic_action<karma::plus<Subject> >
: unary_has_semantic_action<Subject> {};
+ template <typename Subject>
+ struct has_semantic_action<karma::strict_plus<Subject> >
+ : unary_has_semantic_action<Subject> {};
}}}
#endif
Modified: trunk/boost/spirit/home/karma/operator/sequence.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/sequence.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/sequence.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -16,6 +16,7 @@
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/fail_function.hpp>
#include <boost/spirit/home/karma/detail/pass_container.hpp>
+#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/detail/what_function.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
@@ -44,7 +45,6 @@
template <>
struct flatten_tree<karma::domain, proto::tag::shift_left> // flattens <<
: mpl::true_ {};
-
}}
///////////////////////////////////////////////////////////////////////////////
@@ -84,12 +84,36 @@
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
- template <typename Elements>
- struct sequence : nary_generator<sequence<Elements> >
+ namespace detail
+ {
+ template <typename T>
+ struct attribute_size
+ : fusion::result_of::size<T>
+ {};
+
+ template <>
+ struct attribute_size<unused_type>
+ : mpl::int_<0>
+ {};
+
+ template <typename Attribute>
+ inline int attr_size(Attribute const& attr)
+ {
+ return fusion::size(attr);
+ }
+
+ inline int attr_size(unused_type)
+ {
+ return 0;
+ }
+ }
+
+ template <typename Elements, typename Strict, typename Derived>
+ struct base_sequence : nary_generator<Derived>
{
typedef typename traits::sequence_properties<Elements>::type properties;
- sequence(Elements const& elements)
+ base_sequence(Elements const& elements)
: elements(elements) {}
typedef Elements elements_type;
@@ -139,6 +163,14 @@
>::type
>::type attr(attr_);
+ // fail generating if sequences have not the same (logical) length
+ if (Strict::value &&
+ detail::attribute_size<attr_type_>::value !=
+ detail::attr_size(attr_))
+ {
+ return false;
+ }
+
// return false if *any* of the generators fail
return !spirit::any_if(elements, attr, fail_function(sink, ctx, d)
, predicate());
@@ -192,15 +224,47 @@
Elements elements;
};
+ template <typename Elements>
+ struct sequence
+ : base_sequence<Elements, mpl::false_, sequence<Elements> >
+ {
+ typedef base_sequence<Elements, mpl::false_, sequence> base_sequence_;
+
+ sequence(Elements const& subject)
+ : base_sequence_(subject) {}
+ };
+
+ template <typename Elements>
+ struct strict_sequence
+ : base_sequence<Elements, mpl::true_, strict_sequence<Elements> >
+ {
+ typedef base_sequence<Elements, mpl::true_, strict_sequence>
+ base_sequence_;
+
+ strict_sequence(Elements const& subject)
+ : base_sequence_(subject) {}
+ };
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ template <typename Elements, bool strict_mode = false>
+ struct make_sequence
+ : make_nary_composite<Elements, sequence>
+ {};
+
+ template <typename Elements>
+ struct make_sequence<Elements, true>
+ : make_nary_composite<Elements, strict_sequence>
+ {};
+ }
+
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::shift_left, Elements, Modifiers>
- : make_nary_composite<Elements, sequence>
+ : detail::make_sequence<Elements, detail::get_stricttag<Modifiers>::value>
{};
-
}}}
namespace boost { namespace spirit { namespace traits
@@ -209,6 +273,9 @@
struct has_semantic_action<karma::sequence<Elements> >
: nary_has_semantic_action<Elements> {};
+ template <typename Elements>
+ struct has_semantic_action<karma::strict_sequence<Elements> >
+ : nary_has_semantic_action<Elements> {};
}}}
#endif
Modified: trunk/boost/spirit/home/support/common_terminals.hpp
==============================================================================
--- trunk/boost/spirit/home/support/common_terminals.hpp (original)
+++ trunk/boost/spirit/home/support/common_terminals.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -79,6 +79,8 @@
( false_ )
( matches )
( hold )
+ ( strict )
+ ( relaxed )
)
// Here we are reusing proto::lit
Added: trunk/boost/spirit/include/karma_strict_relaxed.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/include/karma_strict_relaxed.hpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -0,0 +1,18 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+#ifndef BOOST_SPIRIT_INCLUDE_KARMA_STRICT_RELAXED
+#define BOOST_SPIRIT_INCLUDE_KARMA_STRICT_RELAXED
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/karma/directive/strict_relaxed.hpp>
+
+#endif
Modified: trunk/libs/spirit/test/karma/kleene.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/kleene.cpp (original)
+++ trunk/libs/spirit/test/karma/kleene.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -16,6 +16,7 @@
#include <boost/spirit/include/karma_action.hpp>
#include <boost/spirit/include/karma_nonterminal.hpp>
#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
@@ -104,6 +105,9 @@
// failing sub-generators
{
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
using namespace boost::assign;
typedef std::pair<char, char> data;
@@ -120,21 +124,33 @@
r = &char_('d') << char_;
BOOST_TEST(test("d", *r, v2));
+ BOOST_TEST(test("d", relaxed[*r], v2));
+ BOOST_TEST(test("", strict[*r], v2));
r = &char_('a') << char_;
BOOST_TEST(test("a", *r, v2));
+ BOOST_TEST(test("a", relaxed[*r], v2));
+ BOOST_TEST(test("a", strict[*r], v2));
r = &char_('g') << char_;
BOOST_TEST(test("g", *r, v2));
+ BOOST_TEST(test("g", relaxed[*r], v2));
+ BOOST_TEST(test("", strict[*r], v2));
r = !char_('d') << char_;
BOOST_TEST(test("abcefg", *r, v2));
+ BOOST_TEST(test("abcefg", relaxed[*r], v2));
+ BOOST_TEST(test("abc", strict[*r], v2));
r = !char_('a') << char_;
BOOST_TEST(test("bcdefg", *r, v2));
+ BOOST_TEST(test("bcdefg", relaxed[*r], v2));
+ BOOST_TEST(test("", strict[*r], v2));
r = !char_('g') << char_;
BOOST_TEST(test("abcdef", *r, v2));
+ BOOST_TEST(test("abcdef", relaxed[*r], v2));
+ BOOST_TEST(test("abcdef", strict[*r], v2));
r = &char_('A') << char_;
BOOST_TEST(test("", *r, v2));
Modified: trunk/libs/spirit/test/karma/list.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/list.cpp (original)
+++ trunk/libs/spirit/test/karma/list.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -6,6 +6,8 @@
#include <boost/config/warning_disable.hpp>
#include <boost/detail/lightweight_test.hpp>
+#include <boost/mpl/print.hpp>
+
#include <boost/spirit/include/karma_operator.hpp>
#include <boost/spirit/include/karma_char.hpp>
#include <boost/spirit/include/karma_string.hpp>
@@ -83,6 +85,9 @@
// failing sub-generators
{
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
typedef std::pair<char, char> data;
std::vector<data> v2;
v2 += std::make_pair('a', 'a'),
@@ -97,21 +102,33 @@
r = &char_('d') << char_;
BOOST_TEST(test("d", r % ',', v2));
+ BOOST_TEST(test("d", relaxed[r % ','], v2));
+ BOOST_TEST(!test("", strict[r % ','], v2));
r = &char_('a') << char_;
BOOST_TEST(test("a", r % ',', v2));
+ BOOST_TEST(test("a", relaxed[r % ','], v2));
+ BOOST_TEST(test("a", strict[r % ','], v2));
r = &char_('g') << char_;
BOOST_TEST(test("g", r % ',', v2));
+ BOOST_TEST(test("g", relaxed[r % ','], v2));
+ BOOST_TEST(!test("", strict[r % ','], v2));
r = !char_('d') << char_;
BOOST_TEST(test("a,b,c,e,f,g", r % ',', v2));
+ BOOST_TEST(test("a,b,c,e,f,g", relaxed[r % ','], v2));
+ BOOST_TEST(test("a,b,c", strict[r % ','], v2));
r = !char_('a') << char_;
BOOST_TEST(test("b,c,d,e,f,g", r % ',', v2));
+ BOOST_TEST(test("b,c,d,e,f,g", relaxed[r % ','], v2));
+ BOOST_TEST(!test("", strict[r % ','], v2));
r = !char_('g') << char_;
BOOST_TEST(test("a,b,c,d,e,f", r % ',', v2));
+ BOOST_TEST(test("a,b,c,d,e,f", relaxed[r % ','], v2));
+ BOOST_TEST(test("a,b,c,d,e,f", strict[r % ','], v2));
r = &char_('A') << char_;
BOOST_TEST(!test("", r % ',', v2));
Modified: trunk/libs/spirit/test/karma/plus.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/plus.cpp (original)
+++ trunk/libs/spirit/test/karma/plus.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -16,6 +16,7 @@
#include <boost/spirit/include/karma_action.hpp>
#include <boost/spirit/include/karma_nonterminal.hpp>
#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
@@ -108,6 +109,9 @@
// failing sub-generators
{
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
using namespace boost::assign;
typedef std::pair<char, char> data;
@@ -124,21 +128,33 @@
r = &char_('d') << char_;
BOOST_TEST(test("d", +r, v2));
+ BOOST_TEST(test("d", relaxed[+r], v2));
+ BOOST_TEST(!test("", strict[+r], v2));
r = &char_('a') << char_;
- BOOST_TEST(test("a",+r, v2));
+ BOOST_TEST(test("a", +r, v2));
+ BOOST_TEST(test("a", relaxed[+r], v2));
+ BOOST_TEST(test("a", strict[+r], v2));
r = &char_('g') << char_;
BOOST_TEST(test("g", +r, v2));
+ BOOST_TEST(test("g", relaxed[+r], v2));
+ BOOST_TEST(!test("", strict[+r], v2));
r = !char_('d') << char_;
BOOST_TEST(test("abcefg", +r, v2));
+ BOOST_TEST(test("abcefg", relaxed[+r], v2));
+ BOOST_TEST(test("abc", strict[+r], v2));
r = !char_('a') << char_;
BOOST_TEST(test("bcdefg", +r, v2));
+ BOOST_TEST(test("bcdefg", relaxed[+r], v2));
+ BOOST_TEST(!test("", strict[+r], v2));
r = !char_('g') << char_;
BOOST_TEST(test("abcdef", +r, v2));
+ BOOST_TEST(test("abcdef", +r, v2));
+ BOOST_TEST(test("abcdef", +r, v2));
r = &char_('A') << char_;
BOOST_TEST(!test("", +r, v2));
Modified: trunk/libs/spirit/test/karma/repeat.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/repeat.cpp (original)
+++ trunk/libs/spirit/test/karma/repeat.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -17,6 +17,7 @@
#include <boost/spirit/include/karma_action.hpp>
#include <boost/spirit/include/karma_nonterminal.hpp>
#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
#include <boost/spirit/include/karma_phoenix_attributes.hpp>
#include <boost/spirit/include/support_argument.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
@@ -142,6 +143,9 @@
// failing sub-generators
{
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
using namespace boost::assign;
namespace karma = boost::spirit::karma;
@@ -163,22 +167,47 @@
r = &char_('d') << char_;
BOOST_TEST(test("d", repeat[r], v2));
+ BOOST_TEST(test("d", relaxed[repeat[r]], v2));
+ BOOST_TEST(test("", strict[repeat[r]], v2));
r = !char_('d') << char_;
BOOST_TEST(test("abcefg", repeat(6)[r], v2));
BOOST_TEST(!test("", repeat(5)[r], v2));
+ BOOST_TEST(test("abcefg", relaxed[repeat(6)[r]], v2));
+ BOOST_TEST(!test("", relaxed[repeat(5)[r]], v2));
+ BOOST_TEST(!test("", strict[repeat(6)[r]], v2));
+ BOOST_TEST(!test("", strict[repeat(5)[r]], v2));
r = !char_('c') << char_;
BOOST_TEST(test("abd", repeat(3)[r], v2));
+ BOOST_TEST(test("abd", relaxed[repeat(3)[r]], v2));
+ BOOST_TEST(!test("", strict[repeat(3)[r]], v2));
r = !char_('a') << char_;
BOOST_TEST(test("bcdef", repeat(3, 5)[r], v2));
BOOST_TEST(test("bcd", repeat(3, 5)[r], v3));
BOOST_TEST(!test("", repeat(4, 5)[r], v3));
+ BOOST_TEST(test("bcdef", relaxed[repeat(3, 5)[r]], v2));
+ BOOST_TEST(test("bcd", relaxed[repeat(3, 5)[r]], v3));
+ BOOST_TEST(!test("", relaxed[repeat(4, 5)[r]], v3));
+ BOOST_TEST(!test("", strict[repeat(3, 5)[r]], v2));
+ BOOST_TEST(!test("", strict[repeat(3, 5)[r]], v3));
+ BOOST_TEST(!test("", strict[repeat(4, 5)[r]], v3));
BOOST_TEST(test("bcd", repeat(3, inf)[r], v3));
BOOST_TEST(test("bcdefg", repeat(3, inf)[r], v2));
BOOST_TEST(!test("", repeat(4, inf)[r], v3));
+
+ r = !char_('g') << char_;
+ BOOST_TEST(test("abcde", repeat(3, 5)[r], v2));
+ BOOST_TEST(test("abcd", repeat(3, 5)[r], v3));
+ BOOST_TEST(!test("", repeat(4, 5)[r], v3));
+ BOOST_TEST(test("abcde", relaxed[repeat(3, 5)[r]], v2));
+ BOOST_TEST(test("abcd", relaxed[repeat(3, 5)[r]], v3));
+ BOOST_TEST(!test("", relaxed[repeat(4, 5)[r]], v3));
+ BOOST_TEST(test("abcde", strict[repeat(3, 5)[r]], v2));
+ BOOST_TEST(test("abcd", strict[repeat(3, 5)[r]], v3));
+ BOOST_TEST(!test("", strict[repeat(5)[r]], v3));
}
{
Modified: trunk/libs/spirit/test/karma/sequence.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/sequence.cpp (original)
+++ trunk/libs/spirit/test/karma/sequence.cpp 2010-04-22 16:25:10 EDT (Thu, 22 Apr 2010)
@@ -17,6 +17,7 @@
#include <boost/spirit/include/karma_action.hpp>
#include <boost/spirit/include/karma_nonterminal.hpp>
#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
#include <boost/spirit/include/support_unused.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
@@ -98,6 +99,39 @@
}
{
+ // element sequence can be shorter and longer than the attribute
+ // sequence
+ using boost::spirit::karma::strict;
+ using boost::spirit::karma::relaxed;
+
+ fusion::vector<char, int, char> p ('a', 12, 'c');
+ BOOST_TEST(test("a12", char_ << int_, p));
+ BOOST_TEST(test_delimited("a 12 ", char_ << int_, p, char(' ')));
+
+ BOOST_TEST(test("a12", relaxed[char_ << int_], p));
+ BOOST_TEST(test_delimited("a 12 ", relaxed[char_ << int_], p, char(' ')));
+
+ BOOST_TEST(!test("", strict[char_ << int_], p));
+ BOOST_TEST(!test_delimited("", strict[char_ << int_], p, char(' ')));
+
+ fusion::vector<char, int> p1 ('a', 12);
+ BOOST_TEST(test("a12c", char_ << int_ << char_('c'), p1));
+ BOOST_TEST(test_delimited("a 12 c ", char_ << int_ << char_('c'),
+ p1, char(' ')));
+
+ BOOST_TEST(test("a12c", relaxed[char_ << int_ << char_('c')], p1));
+ BOOST_TEST(test_delimited("a 12 c ",
+ relaxed[char_ << int_ << char_('c')], p1, char(' ')));
+
+ BOOST_TEST(!test("", strict[char_ << int_ << char_('c')], p1));
+ BOOST_TEST(!test_delimited("", strict[char_ << int_ << char_('c')],
+ p1, char(' ')));
+
+ BOOST_TEST(test("a12", strict[char_ << int_], p1));
+ BOOST_TEST(test_delimited("a 12 ", strict[char_ << int_], p1, char(' ')));
+ }
+
+ {
// if all elements of a sequence have unused parameters, the whole
// sequence has an unused parameter as well
fusion::vector<char, char> p ('a', 'e');
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