Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r69670 - in trunk/boost/spirit: include repository/home/qi/operator repository/home/qi/operator/detail repository/include
From: joel_at_[hidden]
Date: 2011-03-07 21:15:09


Author: djowel
Date: 2011-03-07 21:15:06 EST (Mon, 07 Mar 2011)
New Revision: 69670
URL: http://svn.boost.org/trac/boost/changeset/69670

Log:
keywords missing files
Added:
   trunk/boost/spirit/include/qi_as_string.hpp (contents, props changed)
   trunk/boost/spirit/include/support_info.hpp (contents, props changed)
   trunk/boost/spirit/repository/home/qi/operator/
   trunk/boost/spirit/repository/home/qi/operator/detail/
   trunk/boost/spirit/repository/home/qi/operator/detail/keywords.hpp (contents, props changed)
   trunk/boost/spirit/repository/home/qi/operator/keywords.hpp (contents, props changed)
   trunk/boost/spirit/repository/include/qi_kwd.hpp (contents, props changed)

Added: trunk/boost/spirit/include/qi_as_string.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/include/qi_as_string.hpp 2011-03-07 21:15:06 EST (Mon, 07 Mar 2011)
@@ -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_QI_AS_STRING
+#define BOOST_SPIRIT_INCLUDE_QI_AS_STRING
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/directive/as_string.hpp>
+
+#endif

Added: trunk/boost/spirit/include/support_info.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/include/support_info.hpp 2011-03-07 21:15:06 EST (Mon, 07 Mar 2011)
@@ -0,0 +1,17 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ 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_SUPPORT_INFO
+#define BOOST_SPIRIT_INCLUDE_SUPPORT_INFO
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/support/info.hpp>
+
+#endif

Added: trunk/boost/spirit/repository/home/qi/operator/detail/keywords.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/repository/home/qi/operator/detail/keywords.hpp 2011-03-07 21:15:06 EST (Mon, 07 Mar 2011)
@@ -0,0 +1,2970 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Elements, typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,typename traits::not_is_unused<Attribute>::type());
+
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject_unused(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,unused, NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject_unused(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename traits::make_attribute<attr_type, unused_type> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(unused);
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ template <typename Subject,typename Index>
+ bool call_subject(
+ Subject const &subject, Iterator &first, Iterator const &last
+ , Context& context, Skipper const& skipper
+ , Index& idx ) const
+ {
+ Iterator save = first;
+ if(subject.kwd_loop_parse(first,last,context,skipper,fusion::at_c<Index::value>(attr), NoCasePass::value ))
+ {
+ if(subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ return true;
+ }
+ save = save;
+ return false;
+ }
+
+ template <typename Subject, typename Index, typename Action> bool call_subject(
+ spirit::qi::action<Subject, Action> const &subject, Iterator &first
+ , Iterator const &last, Context& context, Skipper const& skipper
+ , Index &idx) const
+ {
+
+ typedef typename Subject::template attribute<Context, Iterator>::type attr_type;
+ typedef typename fusion::result_of::value_at<Attribute,typename Index::value>::type subject_attribute;
+ typedef typename traits::make_attribute<attr_type, subject_attribute> make_attribute;
+
+ // create an attribute if one is not supplied
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, spirit::qi::domain> transform;
+
+ typename make_attribute::type made_attr = make_attribute::call(fusion::at_c<Index::value>(attr));
+ typename transform::type local_attr = transform::pre(made_attr);
+
+ Iterator save = first;
+ if (subject.subject.kwd_loop_parse(first, last, context, skipper, local_attr, NoCasePass::value ))
+ {
+ if(subject.subject.iter.register_successful_parse(flags[Index::value],counters[Index::value]))
+ {
+ // call the function, passing the attribute, the context.
+ // The client can return false to fail parsing.
+ if (traits::action_dispatch<Subject>()(subject.f, local_attr, context))
+ return true;
+
+ }
+ }
+ // reset iterators if semantic action failed the match
+ // retrospectively
+ first = save;
+ return false;
+ }
+
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, mpl::false_) const{
+
+ //if( fusion::at_c<T::value>(elements).parse_impl( first, last, context, skipper, unused, mpl::false_() ) )
+ return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx, mpl::true_) const{
+ return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
+ }
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ };
+
+}}}}}
+
+#endif
+

Added: trunk/boost/spirit/repository/home/qi/operator/keywords.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/repository/home/qi/operator/keywords.hpp 2011-03-07 21:15:06 EST (Mon, 07 Mar 2011)
@@ -0,0 +1,10204 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/domain.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/fusion/include/value_at.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
+
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, traits::sequence_attribute_transform, Iterator, spirit::qi::domain >::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, mpl::equal_to<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_> parser_visitor_type;
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::true_> no_case_parser_visitor_type;
+
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+ no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, is_same<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+
+ typedef typename kwd_count::asdfa debug;
+
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr, bool case_insensitive_pass) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ , case_insensitive_pass(case_insensitive_pass) {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,case_insensitive_pass,typename traits::not_is_unused<Attribute>::type());
+
+ }
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, bool case_insensitive_pass, mpl::false_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,unused
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx,bool case_insensitive_pass, mpl::true_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,fusion::at_c<T::value>(attr)
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ bool case_insensitive_pass;
+ };
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr, false);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,false);
+ parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,true);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/fusion/include/value_at.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
+
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, mpl::equal_to<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_> parser_visitor_type;
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::true_> no_case_parser_visitor_type;
+
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+ no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, is_same<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+
+ typedef typename kwd_count::asdfa debug;
+
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr, bool case_insensitive_pass) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ , case_insensitive_pass(case_insensitive_pass) {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,case_insensitive_pass,typename traits::not_is_unused<Attribute>::type());
+
+ }
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, bool case_insensitive_pass, mpl::false_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,unused
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx,bool case_insensitive_pass, mpl::true_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,fusion::at_c<T::value>(attr)
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ bool case_insensitive_pass;
+ };
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr, false);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,false);
+ parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,true);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/domain.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/fusion/include/value_at.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
+
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, traits::sequence_attribute_transform, Iterator, spirit::qi::domain >::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, mpl::equal_to<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_> parser_visitor_type;
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::true_> no_case_parser_visitor_type;
+
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+ no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, is_same<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+
+ typedef typename kwd_count::asdfa debug;
+
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr, bool case_insensitive_pass) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ , case_insensitive_pass(case_insensitive_pass) {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,case_insensitive_pass,typename traits::not_is_unused<Attribute>::type());
+
+ }
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, bool case_insensitive_pass, mpl::false_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,unused
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx,bool case_insensitive_pass, mpl::true_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,fusion::at_c<T::value>(attr)
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ bool case_insensitive_pass;
+ };
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr, false);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,false);
+ parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,true);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/fusion/include/value_at.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
+
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, mpl::equal_to<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_> parser_visitor_type;
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::true_> no_case_parser_visitor_type;
+
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+ no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, is_same<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+
+ typedef typename kwd_count::asdfa debug;
+
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr, bool case_insensitive_pass) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ , case_insensitive_pass(case_insensitive_pass) {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,case_insensitive_pass,typename traits::not_is_unused<Attribute>::type());
+
+ }
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, bool case_insensitive_pass, mpl::false_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,unused
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx,bool case_insensitive_pass, mpl::true_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,fusion::at_c<T::value>(attr)
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ bool case_insensitive_pass;
+ };
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr, false);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,false);
+ parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,true);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/domain.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/fusion/include/value_at.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
+
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, traits::sequence_attribute_transform, Iterator, spirit::qi::domain >::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, mpl::equal_to<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_> parser_visitor_type;
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::true_> no_case_parser_visitor_type;
+
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+ no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, is_same<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+
+ typedef typename kwd_count::asdfa debug;
+
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr, bool case_insensitive_pass) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ , case_insensitive_pass(case_insensitive_pass) {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,case_insensitive_pass,typename traits::not_is_unused<Attribute>::type());
+
+ }
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, bool case_insensitive_pass, mpl::false_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,unused
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx,bool case_insensitive_pass, mpl::true_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,fusion::at_c<T::value>(attr)
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ bool case_insensitive_pass;
+ };
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr, false);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,false);
+ parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,true);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/fusion/include/value_at.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
+
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, mpl::equal_to<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_> parser_visitor_type;
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::true_> no_case_parser_visitor_type;
+
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+ no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, is_same<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+
+ typedef typename kwd_count::asdfa debug;
+
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr, bool case_insensitive_pass) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ , case_insensitive_pass(case_insensitive_pass) {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,case_insensitive_pass,typename traits::not_is_unused<Attribute>::type());
+
+ }
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, bool case_insensitive_pass, mpl::false_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,unused
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx,bool case_insensitive_pass, mpl::true_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,fusion::at_c<T::value>(attr)
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ bool case_insensitive_pass;
+ };
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr, false);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,false);
+ parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,true);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/domain.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/fusion/include/value_at.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
+
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, traits::sequence_attribute_transform, Iterator, spirit::qi::domain >::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, mpl::equal_to<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_> parser_visitor_type;
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::true_> no_case_parser_visitor_type;
+
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+ no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, is_same<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+
+ typedef typename kwd_count::asdfa debug;
+
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr, bool case_insensitive_pass) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ , case_insensitive_pass(case_insensitive_pass) {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,case_insensitive_pass,typename traits::not_is_unused<Attribute>::type());
+
+ }
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, bool case_insensitive_pass, mpl::false_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,unused
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx,bool case_insensitive_pass, mpl::true_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,fusion::at_c<T::value>(attr)
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ bool case_insensitive_pass;
+ };
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr, false);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,false);
+ parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,true);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/fusion/include/value_at.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/spirit/repository/home/qi/operator/detail/keywords.hpp>
+
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, mpl::equal_to<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef repository::qi::detail::parse_dispatcher<Elements,Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::false_> parser_visitor_type;
+
+ typedef detail::parse_dispatcher<Elements, Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ , mpl::true_> no_case_parser_visitor_type;
+
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+ no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ 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_KEYWORDS_OR_MARCH_13_2007_1145PM)
+#define SPIRIT_KEYWORDS_OR_MARCH_13_2007_1145PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/qi/detail/permute_function.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/fusion/include/iter_fold.hpp>
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+#include <boost/array.hpp>
+#include <boost/spirit/home/qi/string/symbols.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/spirit/home/qi/action/action.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_operator<qi::domain, proto::tag::divides > // enables /
+ : mpl::true_ {};
+
+ template <>
+ struct flatten_tree<qi::domain, proto::tag::divides> // flattens /
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace repository { namespace qi
+{
+
+ // kwd directive parser type identification
+ namespace detail
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+
+
+ }
+
+ // kwd directive type query
+ template <typename T>
+ struct is_kwd_parser : detail::has_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_kwd_parser_id<Subject> {};
+
+ // Keywords operator
+ template <typename Elements, typename Modifiers>
+ struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
+ {
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ // Put all the element attributes in a tuple
+ typedef typename traits::build_attribute_sequence<
+ Elements, Context, mpl::identity, Iterator>::type
+ all_attributes;
+
+ // Now, build a fusion vector over the attributes. Note
+ // that build_fusion_vector 1) removes all unused attributes
+ // and 2) may return unused_type if all elements have
+ // unused_type(s).
+ typedef typename
+ traits::build_fusion_vector<all_attributes>::type
+ type;
+ };
+
+ /// Make sure that all subjects are of the kwd type
+ typedef typename mpl::count_if<
+ Elements,
+ mpl::not_<
+ is_kwd_parser<
+ mpl::_1
+ >
+ >
+ > non_kwd_subject_count;
+
+ /// If the assertion fails here then you probably forgot to wrap a
+ /// subject of the / operator in a kwd directive
+ BOOST_MPL_ASSERT_RELATION( non_kwd_subject_count::value, ==, 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_parser_tags
+ //
+ // Builds a boost::variant from an mpl::range_c in order to "mark" every
+ // parser of the fusion sequence. The integer constant is used in the parser
+ // dispatcher functor in order to use the parser corresponding to the recognised
+ // keyword.
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Sequence>
+ struct build_parser_tags
+ {
+ // Get the sequence size
+ typedef typename mpl::size< Sequence >::type sequence_size;
+
+ // Create an integer_c constant for every parser in the sequence
+ typedef typename mpl::range_c<int, 0, sequence_size::value>::type int_range;
+
+ // Transform the range_c to an mpl vector in order to be able to transform it into a variant
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type int_vector;
+
+ // Build the variant type containing the indexes of the parsers
+ typedef typename
+ spirit::detail::as_variant<
+ int_vector >::type type;
+ };
+
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename build_parser_tags< Elements >::type parser_index_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_char_type_sequence
+ //
+ // Build a fusion sequence from the kwd directive specified character type.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_char_type_sequence
+ {
+ struct element_char_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::char_type type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::char_type type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_char_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_char_type>::type
+ type;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_keyword_char_type
+ //
+ // Collapses the character type comming from the subject kwd parsers and
+ // and checks that they are all identical (necessary in order to be able
+ // to build a tst parser to parse the keywords.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence>
+ struct get_keyword_char_type
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::fold<
+ Sequence, mpl::vector<>,
+ mpl::if_<
+ mpl::contains<mpl::_1, mpl::_2>,
+ mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
+ >
+ >::type
+ no_duplicate_char_types;
+
+ // If the compiler traps here this means you mixed
+ // character type for the keywords specified in the
+ // kwd directive sequence.
+ BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
+
+ typedef typename mpl::front<no_duplicate_char_types>::type type;
+
+ };
+
+ /// Get the character type for the tst parser
+ typedef typename build_char_type_sequence< Elements >::type char_types;
+ typedef typename get_keyword_char_type< char_types >::type char_type;
+
+ /// Our symbols container
+ typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+
+ // Filter functor used for case insensitive parsing
+ template <typename CharEncoding>
+ struct no_case_filter
+ {
+ char_type operator()(char_type ch) const
+ {
+ return static_cast<char_type>(CharEncoding::tolower(ch));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // build_case_type_sequence
+ //
+ // Build a fusion sequence from the kwd/ikwd directives
+ // in order to determine if case sensitive and case insensitive
+ // keywords have been mixed.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence >
+ struct build_case_type_sequence
+ {
+ struct element_case_type
+ {
+ template <typename T>
+ struct result;
+
+ template <typename F, typename Element>
+ struct result<F(Element)>
+ {
+ typedef typename Element::no_case_keyword type;
+
+ };
+ template <typename F, typename Element,typename Action>
+ struct result<F(spirit::qi::action<Element,Action>) >
+ {
+ typedef typename Element::no_case_keyword type;
+ };
+
+ // never called, but needed for decltype-based result_of (C++0x)
+ template <typename Element>
+ typename result<element_case_type(Element)>::type
+ operator()(Element&) const;
+ };
+
+ // Compute the list of character types of the child kwd directives
+ typedef typename
+ fusion::result_of::transform<Sequence, element_case_type>::type
+ type;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // get_nb_case_types
+ //
+ // Counts the number of entries in the case type sequence matching the
+ // CaseType parameter (mpl::true_ -> case insensitve
+ // , mpl::false_ -> case sensitive
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Sequence,typename CaseType>
+ struct get_nb_case_types
+ {
+ // Make sure each of the types occur only once in the type list
+ typedef typename
+ mpl::count_if<
+ Sequence, is_same<mpl::_,CaseType>
+ >::type type;
+
+
+ };
+ // Build the case type sequence
+ typedef typename build_case_type_sequence<Elements>::type case_type_sequence;
+ // Count the number of case sensitive entries and case insensitve entries
+ typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
+ typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
+
+ typedef typename kwd_count::asdfa debug;
+
+ // Get the size of the original sequence
+ typedef typename mpl::size<Elements>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::equal_to< ikwd_count, nb_elements>::type all_ikwd;
+ typedef typename mpl::equal_to< kwd_count, nb_elements>::type all_kwd;
+
+ typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
+
+ // Do we have a no case modifier
+ typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
+
+ // Should the no_case filter always be used ?
+ typedef typename mpl::or_<
+ no_case_modifier,
+ mpl::and_<
+ all_directives_of_same_type
+ ,all_ikwd
+ >
+ >::type
+ no_case;
+
+ typedef no_case_filter<
+ typename spirit::detail::get_encoding_with_case<
+ Modifiers
+ , char_encoding::standard
+ , no_case::value>::type>
+ nc_filter;
+ // Determine the standard case filter type
+ typedef typename mpl::if_<
+ no_case
+ , nc_filter
+ , spirit::qi::tst_pass_through >::type
+ filter_type;
+
+
+ // build a bool array and an integer array which will be used to
+ // check that the repetition constraints of the kwd parsers are
+ // met and bail out a soon as possible
+ typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
+ typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ template< typename Sequence >
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,flags_type &flags) :
+ lookup(lookup)
+ ,flags(flags)
+ {}
+
+ typedef typename fusion::result_of::begin< Sequence >::type sequence_begin;
+
+ template <typename T>
+ int operator()(const int i, const T &parser) const
+ {
+ // Determine the current position being handled
+ typedef typename fusion::result_of::distance< sequence_begin, T >::type position_raw;
+ // Transform the position to a parser index tag
+ typedef typename mpl::integral_c<int,position_raw::value> position;
+
+ return call(i,fusion::deref(parser),position());
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call( const int i, const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.subject.keyword.str),
+ traits::get_end<char_type>(parser.subject.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.subject.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const int i, const T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(parser.keyword.str),
+ traits::get_end<char_type>(parser.keyword.str),
+ position
+ );
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+
+ shared_ptr<keywords_type> lookup;
+ flags_type & flags;
+ };
+
+
+
+ // Variant visitor class which handles dispatching the parsing to the selected parser
+ // This also handles passing the correct attributes and flags/counters to the subject parsers
+
+ template < typename Iterator ,typename Context ,typename Skipper
+ ,typename Flags ,typename Counters ,typename Attribute>
+ class parse_dispatcher
+ : public boost::static_visitor<bool>
+ {
+ public:
+ parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Flags &flags, Counters &counters, Attribute& attr, bool case_insensitive_pass) :
+ elements(elements), first(first), last(last)
+ , context(context), skipper(skipper)
+ , flags(flags),counters(counters), attr(attr)
+ , case_insensitive_pass(case_insensitive_pass) {}
+
+ template<typename T> bool operator()(T& idx) const
+ {
+ return call(idx,case_insensitive_pass,typename traits::not_is_unused<Attribute>::type());
+
+ }
+ // Handle unused attributes
+ template <typename T> bool call(T &idx, bool case_insensitive_pass, mpl::false_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,unused
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+ // Handle normal attributes
+ template <typename T> bool call(T &idx,bool case_insensitive_pass, mpl::true_) const{
+ return fusion::at_c<T::value>(elements).parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,fusion::at_c<T::value>(attr)
+ ,flags[T::value],counters[T::value]
+ ,case_insensitive_pass
+ );
+ }
+
+
+ const Elements &elements;
+ Iterator &first;
+ const Iterator &last;
+ Context & context;
+ const Skipper &skipper;
+ Flags &flags;
+ Counters &counters;
+ Attribute &attr;
+ bool case_insensitive_pass;
+ };
+
+ keywords(Elements const& elements) :
+ elements(elements)
+ , lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ keyword_entry_adder<Elements> f1(lookup,flags_init);
+ fusion::iter_fold(this->elements,0,f1);
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+
+ // Select which parse function to call
+ // We need to handle the case where kwd / ikwd directives have been mixed
+ // This is where we decide which function should be called.
+ return parse_impl(first, last, context, skipper, attr_,
+ typename mpl::or_<all_directives_of_same_type, no_case>::type()
+ );
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+ parser_visitor_type parse_visitor(elements, first, last
+ , context, skipper, flags
+ , counters, attr, false);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+
+ spirit::qi::skip_over(first, last, skipper);
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, filter_type()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Handle the mixed kwd and ikwd case
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse_impl(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_,mpl::false_) const
+ {
+
+ // wrap the attribute in a tuple if it is not a tuple
+ typename traits::wrap_if_not_tuple<Attribute>::type attr(attr_);
+
+ flags_type flags(flags_init);
+ //flags.assign(false);
+
+ counters_type counters;
+ counters.assign(0);
+
+ typedef parse_dispatcher<Iterator, Context, Skipper
+ , flags_type, counters_type
+ , typename traits::wrap_if_not_tuple<Attribute>::type
+ > parser_visitor_type;
+
+ parser_visitor_type parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,false);
+ parser_visitor_type no_case_parse_visitor(elements,first,last
+ ,context,skipper,flags,counters,attr,true);
+
+ // We have a bool array 'flags' with one flag for each parser as well as a 'counter'
+ // array.
+ // The kwd directive sets and increments the counter when a successeful parse occured
+ // as well as the slot of the corresponding parser to true in the flags array as soon
+ // the minimum repetition requirement is met and keeps that value to true as long as
+ // the maximum repetition requirement is met.
+ // The parsing takes place here in two steps:
+ // 1) parse a keyword and fetch the parser index associated with that keyword
+ // 2) call the associated parser and store the parsed value in the matching attribute.
+ Iterator save = first;
+ while(true)
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ // First pass case sensitive
+ Iterator saved_first = first;
+ if (parser_index_type* val_ptr
+ = lookup->find(first, last, spirit::qi::tst_pass_through()))
+ {
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ first = save;
+ return false;
+ }
+ save = first;
+ }
+ else
+ {
+ // Check that we are leaving the keywords parser in a successfull state
+ BOOST_FOREACH(bool &valid,flags)
+ {
+ if(!valid)
+ {
+ first = save;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ info result("keywords");
+ fusion::for_each(elements,
+ spirit::detail::what_function<Context>(result, context));
+ return result;
+ }
+ flags_type flags_init;
+ Elements elements;
+ shared_ptr<keywords_type> lookup;
+
+ };
+}}}}
+
+namespace boost { namespace spirit { namespace qi {
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Elements, typename Modifiers >
+ struct make_composite<proto::tag::divides, Elements, Modifiers >
+ {
+ typedef repository::qi::keywords<Elements,Modifiers> result_type;
+ result_type operator()(Elements ref, unused_type) const
+ {
+ return result_type(ref);
+ }
+ };
+
+
+}}}
+
+namespace boost { namespace spirit { namespace traits
+{
+ // We specialize this for keywords (see support/attributes.hpp).
+ // For keywords, we only wrap the attribute in a tuple IFF
+ // it is not already a fusion tuple.
+ template <typename Elements, typename Modifiers,typename Attribute>
+ struct pass_attribute<repository::qi::keywords<Elements,Modifiers>, Attribute>
+ : wrap_if_not_tuple<Attribute> {};
+
+ template <typename Elements, typename Modifiers>
+ struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
+ : nary_has_semantic_action<Elements> {};
+}}}
+
+#endif
+

Added: trunk/boost/spirit/repository/include/qi_kwd.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/repository/include/qi_kwd.hpp 2011-03-07 21:15:06 EST (Mon, 07 Mar 2011)
@@ -0,0 +1,38 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2011 Thomas Bernard
+ 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_QI_KWD
+#define BOOST_SPIRIT_INCLUDE_QI_KWD
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/repository/home/qi/directive/kwd.hpp>
+
+#endif
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2011 Thomas Bernard
+ 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_QI_KWD
+#define BOOST_SPIRIT_INCLUDE_QI_KWD
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/repository/home/qi/directive/kwd.hpp>
+
+#endif


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