|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r55008 - in trunk/boost/spirit: home/qi/detail home/qi/nonterminal home/support home/support/iterators home/support/iterators/detail repository/home/qi
From: hartmut.kaiser_at_[hidden]
Date: 2009-07-17 23:35:25
Author: hkaiser
Date: 2009-07-17 23:35:24 EDT (Fri, 17 Jul 2009)
New Revision: 55008
URL: http://svn.boost.org/trac/boost/changeset/55008
Log:
Spirit: integrated multi_pass iterator with expectation points and error handling
Added:
trunk/boost/spirit/home/support/multi_pass_wrapper.hpp (contents, props changed)
Text files modified:
trunk/boost/spirit/home/qi/detail/expect_function.hpp | 11 +++++++
trunk/boost/spirit/home/qi/nonterminal/error_handler.hpp | 61 ++++++++++++++++++++++++++++++++++++++-
trunk/boost/spirit/home/support/iterators/detail/combine_policies.hpp | 10 +++++
trunk/boost/spirit/home/support/iterators/multi_pass.hpp | 38 +++++++++++++++++++++++-
trunk/boost/spirit/home/support/iterators/multi_pass_fwd.hpp | 26 +++++++++++++++++
trunk/boost/spirit/repository/home/qi/flush_multi_pass.hpp | 18 -----------
6 files changed, 142 insertions(+), 22 deletions(-)
Modified: trunk/boost/spirit/home/qi/detail/expect_function.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/expect_function.hpp (original)
+++ trunk/boost/spirit/home/qi/detail/expect_function.hpp 2009-07-17 23:35:24 EDT (Fri, 17 Jul 2009)
@@ -8,6 +8,7 @@
#define SPIRIT_EXPECT_FUNCTION_APR_29_2007_0558PM
#include <boost/spirit/home/support/unused.hpp>
+#include <boost/spirit/home/support/multi_pass_wrapper.hpp>
namespace boost { namespace spirit { namespace qi { namespace detail
{
@@ -33,6 +34,11 @@
template <typename Component, typename Attribute>
bool operator()(Component const& component, Attribute& attr) const
{
+ // if this is not the first component in the expect chain we
+ // need to flush any multi_pass iterator we might be acting on
+ if (!is_first)
+ spirit::traits::clear_queue(first);
+
// if we are testing the first component in the sequence,
// return true if the parser fails, if this not the first
// component, throw exception if the parser fails
@@ -53,6 +59,11 @@
template <typename Component>
bool operator()(Component const& component) const
{
+ // if this is not the first component in the expect chain we
+ // need to flush any multi_pass iterator we might be acting on
+ if (!is_first)
+ spirit::traits::clear_queue(first);
+
// if we are testing the first component in the sequence,
// return true if the parser fails, if this not the first
// component, throw exception if the parser fails
Modified: trunk/boost/spirit/home/qi/nonterminal/error_handler.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/nonterminal/error_handler.hpp (original)
+++ trunk/boost/spirit/home/qi/nonterminal/error_handler.hpp 2009-07-17 23:35:24 EDT (Fri, 17 Jul 2009)
@@ -13,7 +13,9 @@
#include <boost/spirit/home/qi/operator/expect.hpp>
#include <boost/spirit/home/qi/nonterminal/rule.hpp>
+#include <boost/spirit/home/support/multi_pass_wrapper.hpp>
#include <boost/function.hpp>
+#include <boost/assert.hpp>
namespace boost { namespace spirit { namespace qi
{
@@ -25,6 +27,42 @@
, rethrow
};
+ namespace detail
+ {
+ // Helper template allowing to manage the inhibit clear queue flag in
+ // a multi_pass iterator. This is the usual specialization used for
+ // anything but a multi_pass iterator.
+ template <typename Iterator, bool active>
+ struct reset_on_exit
+ {
+ reset_on_exit(Iterator& it) {}
+ };
+
+ // For 'retry' or 'fail' error handlers we need to inhibit the flushing
+ // of the internal multi_pass buffers which otherwise might happen at
+ // deterministic expectation points inside the encapsulated right hand
+ // side of rule.
+ template <typename Iterator>
+ struct reset_on_exit<Iterator, true>
+ {
+ reset_on_exit(Iterator& it)
+ : it_(it)
+ , inhibit_clear_queue_(spirit::traits::inhibit_clear_queue(it))
+ {
+ spirit::traits::inhibit_clear_queue(it_, true);
+ }
+
+ ~reset_on_exit()
+ {
+ // reset inhibit flag in multi_pass on exit
+ spirit::traits::inhibit_clear_queue(it_, inhibit_clear_queue_);
+ }
+
+ Iterator& it_;
+ bool inhibit_clear_queue_;
+ };
+ }
+
template <
typename Iterator, typename Context
, typename Skipper, typename F, error_handler_result action
@@ -48,6 +86,11 @@
Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper) const
{
+ typedef qi::detail::reset_on_exit<Iterator
+ , traits::is_multi_pass<Iterator>::value &&
+ (action == retry || action == fail)> on_exit_type;
+
+ on_exit_type on_exit(first);
while (true)
{
try
@@ -71,10 +114,24 @@
params args(first, last, x.first, x.what);
f(args, context, r);
+ // The assertions below will fire if you are using a
+ // multi_pass as the underlying iterator, one of your error
+ // handlers forced to 'fail' or 'retry' its guarded rule,
+ // and the error handler has not been instantiated using
+ // either 'fail' or 'retry' in the first place. Please see
+ // the mutli_pass docs for more information.
switch (r)
{
- case fail: return false;
- case retry: continue;
+ case fail:
+ BOOST_ASSERT(
+ traits::is_multi_pass<Iterator>::value &&
+ action != retry && action != fail);
+ return false;
+ case retry:
+ BOOST_ASSERT(
+ traits::is_multi_pass<Iterator>::value &&
+ action != retry && action != fail);
+ continue;
case accept: return true;
case rethrow: throw x;
}
Modified: trunk/boost/spirit/home/support/iterators/detail/combine_policies.hpp
==============================================================================
--- trunk/boost/spirit/home/support/iterators/detail/combine_policies.hpp (original)
+++ trunk/boost/spirit/home/support/iterators/detail/combine_policies.hpp 2009-07-17 23:35:24 EDT (Fri, 17 Jul 2009)
@@ -460,7 +460,15 @@
typedef multi_pass_shared<T, ownership_policy, checking_policy
, input_policy, storage_policy> shared_base_type;
- explicit shared(T const& input) : shared_base_type(input) {}
+ explicit shared(T const& input)
+ : shared_base_type(input), inhibit_clear_queue_(false) {}
+
+ // This is needed for the correct implementation of expectation
+ // points. Normally expectation points flush any multi_pass
+ // iterator they may act on, but if the corresponding error handler
+ // is of type 'retry' no flushing of the internal buffers should be
+ // executed (even if explicitly requested).
+ bool inhibit_clear_queue_;
};
};
Modified: trunk/boost/spirit/home/support/iterators/multi_pass.hpp
==============================================================================
--- trunk/boost/spirit/home/support/iterators/multi_pass.hpp (original)
+++ trunk/boost/spirit/home/support/iterators/multi_pass.hpp 2009-07-17 23:35:24 EDT (Fri, 17 Jul 2009)
@@ -129,9 +129,19 @@
return tmp;
}
- void clear_queue()
+ void clear_queue(BOOST_SCOPED_ENUM(traits::clear_mode) mode =
+ traits::clear_mode::clear_if_enabled)
{
- policies_base_type::clear_queue(*this);
+ if (mode == traits::clear_mode::clear_always || !inhibit_clear_queue())
+ policies_base_type::clear_queue(*this);
+ }
+ bool inhibit_clear_queue() const
+ {
+ return this->member->inhibit_clear_queue_;
+ }
+ void inhibit_clear_queue(bool flag)
+ {
+ this->member->inhibit_clear_queue_ = flag;
}
bool operator==(multi_pass const& y) const
@@ -211,6 +221,30 @@
x.swap(y);
}
+ // define special functions allowing to integrate any multi_pass iterator
+ // with expectation points
+ namespace traits
+ {
+ template <typename T, typename Policies>
+ void clear_queue(multi_pass<T, Policies>& mp
+ , BOOST_SCOPED_ENUM(traits::clear_mode) mode)
+ {
+ mp.clear_queue(mode);
+ }
+
+ template <typename T, typename Policies>
+ void inhibit_clear_queue(multi_pass<T, Policies>& mp, bool flag)
+ {
+ mp.inhibit_clear_queue(flag);
+ }
+
+ template <typename T, typename Policies>
+ bool inhibit_clear_queue(multi_pass<T, Policies>& mp)
+ {
+ return mp.inhibit_clear_queue();
+ }
+ }
+
}} // namespace boost::spirit
#endif
Modified: trunk/boost/spirit/home/support/iterators/multi_pass_fwd.hpp
==============================================================================
--- trunk/boost/spirit/home/support/iterators/multi_pass_fwd.hpp (original)
+++ trunk/boost/spirit/home/support/iterators/multi_pass_fwd.hpp 2009-07-17 23:35:24 EDT (Fri, 17 Jul 2009)
@@ -1,5 +1,6 @@
/*=============================================================================
Copyright (c) 2007 Tobias Schwinger
+ Copyright (c) 2001-2009 Hartmut Kaiser
http://spirit.sourceforge.net/
Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -9,6 +10,7 @@
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_FWD_APR_18_2008_1102AM
#include <cstddef>
+#include <boost/spirit/home/support/multi_pass_wrapper.hpp>
namespace boost { namespace spirit {
@@ -63,5 +65,29 @@
}} // namespace boost::spirit
+namespace boost { namespace spirit { namespace traits
+{
+ // declare special functions allowing to integrate any multi_pass iterator
+ // with expectation points
+
+ // multi_pass iterators require special handling (for the non-specialized
+ // versions of these functions see support/multi_pass_wrapper.hpp)
+ template <typename T, typename Policies>
+ void clear_queue(multi_pass<T, Policies>&
+ , BOOST_SCOPED_ENUM(clear_mode) mode = clear_mode::clear_if_enabled);
+
+ template <typename T, typename Policies>
+ void inhibit_clear_queue(multi_pass<T, Policies>&, bool);
+
+ template <typename T, typename Policies>
+ bool inhibit_clear_queue(multi_pass<T, Policies>&);
+
+ // Helper template to recognize a multi_pass iterator. This specialization
+ // will be instantiated for any multi_pass iterator.
+ template <typename T, typename Policies>
+ struct is_multi_pass<multi_pass<T, Policies> > : mpl::true_ {};
+
+}}}
+
#endif
Added: trunk/boost/spirit/home/support/multi_pass_wrapper.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/support/multi_pass_wrapper.hpp 2009-07-17 23:35:24 EDT (Fri, 17 Jul 2009)
@@ -0,0 +1,47 @@
+// Copyright (c) 2001-2009 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_ITERATOR_MULTI_PASS_WRAPPER_JUL_12_2009_0914PM)
+#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_WRAPPER_JUL_12_2009_0914PM
+
+#include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
+
+namespace boost { namespace spirit { namespace traits
+{
+ // declare special functions allowing to integrate any multi_pass iterator
+ // with expectation points
+
+ // normal iterators require no special handling
+ BOOST_SCOPED_ENUM_START(clear_mode)
+ {
+ clear_if_enabled,
+ clear_always
+ };
+ BOOST_SCOPED_ENUM_END
+
+ template <typename Iterator>
+ void clear_queue(Iterator&
+ , BOOST_SCOPED_ENUM(clear_mode) mode = clear_mode::clear_if_enabled)
+ {}
+
+ template <typename Iterator>
+ void inhibit_clear_queue(Iterator&, bool)
+ {}
+
+ template <typename Iterator>
+ bool inhibit_clear_queue(Iterator&)
+ {
+ return false;
+ }
+
+ // Helper template to recognize a multi_pass iterator. This specialization
+ // will be instantiated for any non-multi_pass iterator.
+ template <typename Iterator>
+ struct is_multi_pass : mpl::false_ {};
+
+}}}
+
+#endif
+
Modified: trunk/boost/spirit/repository/home/qi/flush_multi_pass.hpp
==============================================================================
--- trunk/boost/spirit/repository/home/qi/flush_multi_pass.hpp (original)
+++ trunk/boost/spirit/repository/home/qi/flush_multi_pass.hpp 2009-07-17 23:35:24 EDT (Fri, 17 Jul 2009)
@@ -40,22 +40,6 @@
using repository::flush_multi_pass_type;
using repository::flush_multi_pass;
- namespace detail
- {
- // normal iterators require no special handling
- template <typename Iterator>
- void clear_queue(Iterator& it)
- {
- }
-
- // where a multi_pass has some means to clear the internal buffers
- template<typename T, typename Policies>
- void clear_queue(multi_pass<T, Policies>& it)
- {
- it.clear_queue();
- }
- }
-
///////////////////////////////////////////////////////////////////////////
// for a flush_multi_pass_parser generated parser
struct flush_multi_pass_parser
@@ -73,7 +57,7 @@
, Context& context, Skipper const& skipper
, Attribute& attr) const
{
- repository::qi::detail::clear_queue(first);
+ spirit::traits::clear_queue(first, traits::clear_mode::clear_always);
return 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