summaryrefslogtreecommitdiff
path: root/boost/spirit/repository/home/qi
diff options
context:
space:
mode:
Diffstat (limited to 'boost/spirit/repository/home/qi')
-rw-r--r--boost/spirit/repository/home/qi/directive/kwd.hpp689
-rw-r--r--boost/spirit/repository/home/qi/operator/detail/keywords.hpp634
-rw-r--r--boost/spirit/repository/home/qi/operator/keywords.hpp420
3 files changed, 1364 insertions, 379 deletions
diff --git a/boost/spirit/repository/home/qi/directive/kwd.hpp b/boost/spirit/repository/home/qi/directive/kwd.hpp
index 79fdc2f6dc..bba1a78448 100644
--- a/boost/spirit/repository/home/qi/directive/kwd.hpp
+++ b/boost/spirit/repository/home/qi/directive/kwd.hpp
@@ -35,50 +35,98 @@ namespace boost { namespace spirit
struct use_directive<qi::domain
, terminal_ex<repository::tag::kwd // enables kwd(key)[p]
, fusion::vector1<T > >
- > : traits::is_string<T> {};
+ > : mpl::true_ {};
template < typename T>
struct use_directive<qi::domain
, terminal_ex<repository::tag::ikwd // enables ikwd(key)[p]
, fusion::vector1<T > >
- > : traits::is_string<T> {};
+ > : mpl::true_ {};
+ template < typename T>
+ struct use_directive<qi::domain
+ , terminal_ex<repository::tag::dkwd // enables dkwd(key)[p]
+ , fusion::vector1<T > >
+ > : mpl::true_ {};
+ template < typename T>
+ struct use_directive<qi::domain
+ , terminal_ex<repository::tag::idkwd // enables idkwd(key)[p]
+ , fusion::vector1<T > >
+ > : mpl::true_ {};
+
+
template < typename T1, typename T2>
struct use_directive<qi::domain
, terminal_ex<repository::tag::kwd // enables kwd(key,exact)[p]
, fusion::vector2< T1, T2 > >
- > : traits::is_string<T1> {};
+ > : mpl::true_ {};
template < typename T1, typename T2>
struct use_directive<qi::domain
, terminal_ex<repository::tag::ikwd // enables ikwd(key,exact)[p]
, fusion::vector2< T1, T2 > >
- > : traits::is_string<T1> {};
+ > : mpl::true_ {};
template < typename T1, typename T2>
struct use_directive<qi::domain
+ , terminal_ex<repository::tag::dkwd // enables dkwd(key,exact)[p]
+ , fusion::vector2< T1, T2 > >
+ > : mpl::true_ {};
+
+ template < typename T1, typename T2>
+ struct use_directive<qi::domain
+ , terminal_ex<repository::tag::idkwd // enables idkwd(key,exact)[p]
+ , fusion::vector2< T1, T2 > >
+ > : mpl::true_ {};
+
+ template < typename T1, typename T2>
+ struct use_directive<qi::domain
, terminal_ex<repository::tag::kwd // enables kwd(min, max)[p]
, fusion::vector3< T1, T2, T2 > >
- > : traits::is_string<T1> {};
+ > : mpl::true_ {};
template < typename T1, typename T2>
struct use_directive<qi::domain
, terminal_ex<repository::tag::ikwd // enables ikwd(min, max)[p]
, fusion::vector3< T1, T2, T2 > >
- > : traits::is_string<T1> {};
+ > : mpl::true_ {};
+
+ template < typename T1, typename T2>
+ struct use_directive<qi::domain
+ , terminal_ex<repository::tag::dkwd // enables dkwd(min, max)[p]
+ , fusion::vector3< T1, T2, T2 > >
+ > : mpl::true_ {};
template < typename T1, typename T2>
struct use_directive<qi::domain
+ , terminal_ex<repository::tag::idkwd // enables idkwd(min, max)[p]
+ , fusion::vector3< T1, T2, T2 > >
+ > : mpl::true_ {};
+
+ template < typename T1, typename T2>
+ struct use_directive<qi::domain
, terminal_ex<repository::tag::kwd // enables kwd(min, inf)[p]
, fusion::vector3<T1, T2, inf_type > >
- > : traits::is_string<T1> {};
+ > : mpl::true_ {};
template < typename T1, typename T2>
struct use_directive<qi::domain
, terminal_ex<repository::tag::ikwd // enables ikwd(min, inf)[p]
, fusion::vector3<T1, T2, inf_type > >
- > : traits::is_string<T1> {};
+ > : mpl::true_ {};
+
+ template < typename T1, typename T2>
+ struct use_directive<qi::domain
+ , terminal_ex<repository::tag::dkwd // enables dkwd(min, inf)[p]
+ , fusion::vector3<T1, T2, inf_type > >
+ > : mpl::true_ {};
+
+ template < typename T1, typename T2>
+ struct use_directive<qi::domain
+ , terminal_ex<repository::tag::idkwd // enables idkwd(min, inf)[p]
+ , fusion::vector3<T1, T2, inf_type > >
+ > : mpl::true_ {};
/* template <> // enables *lazy* kwd(exact)[p]
@@ -102,6 +150,8 @@ namespace boost { namespace spirit { namespace repository { namespace qi
{
using repository::kwd;
using repository::ikwd;
+ using repository::dkwd;
+ using repository::idkwd;
using spirit::inf;
using spirit::inf_type;
@@ -225,13 +275,14 @@ template <typename T>
int &counter;
};
- template <typename Subject, typename KeywordType, typename LoopIter , typename NoCase >
- struct kwd_parser : spirit::qi::unary_parser<kwd_parser<Subject, KeywordType, LoopIter , NoCase > >
+ template <typename Subject, typename KeywordType, typename LoopIter , typename NoCase, typename Distinct >
+ struct kwd_parser : spirit::qi::unary_parser<kwd_parser<Subject, KeywordType, LoopIter , NoCase, Distinct > >
{
struct kwd_parser_id;
typedef Subject subject_type;
typedef NoCase no_case_keyword;
+ typedef Distinct distinct;
typedef typename
remove_const<typename traits::char_type_of<KeywordType>::type>::type
@@ -256,6 +307,13 @@ template <typename T>
, LoopIter const& iter)
: subject(subject), iter(iter), keyword(keyword) {}
+ template<typename CharEncoding>
+ kwd_parser(Subject const& subject
+ , typename add_reference<KeywordType>::type keyword
+ , LoopIter const& iter, CharEncoding encoding)
+ : subject(subject), iter(iter), keyword(keyword,encoding) {}
+
+
// Call the subject parser on a non container attribute
template <typename Iterator, typename Context
, typename Skipper, typename Attribute>
@@ -329,12 +387,14 @@ template <typename T>
, mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
>::type predicate;
+
// Parse the keyword
bool flag = iter.flag_init();
int counter = 0;
Iterator save = first;
spirit::qi::skip_over(first, last, skipper);
if(keyword.parse(first,last,context,skipper,unused)){
+ if((!distinct::value) || skipper.parse(first,last,unused,unused,unused)){
// Followed by the subject parser
spirit::qi::skip_over(first, last, skipper);
if(parse_impl(first,last,context,skipper,attr, predicate()))
@@ -342,6 +402,7 @@ template <typename T>
return iter.register_successful_parse(flag,counter);
}
}
+ }
first = save;
return flag;
}
@@ -350,16 +411,29 @@ template <typename T>
template <typename Context>
info what(Context& context) const
{
+ if(distinct::value){
if(no_case_keyword::value)
+ return info("idkwd", subject.what(context));
+ else
+ return info("dkwd", subject.what(context));
+ }
+ else
+ {
+ if(no_case_keyword::value)
return info("ikwd", subject.what(context));
else
return info("kwd", subject.what(context));
}
+ }
Subject subject;
LoopIter iter;
- spirit::qi::literal_string<KeywordType, true> keyword;
+ typedef typename mpl::if_<
+ no_case_keyword,
+ spirit::qi::no_case_literal_string< KeywordType, true>,
+ spirit::qi::literal_string<KeywordType, true> >::type keyword_string_type;
+ keyword_string_type keyword;
private:
// silence MSVC warning C4512: assignment operator could not be generated
kwd_parser& operator= (kwd_parser const&);
@@ -376,6 +450,151 @@ template <typename T>
};
+
+template <typename Subject, typename KeywordType, typename LoopIter, typename Distinct>
+ struct complex_kwd_parser : spirit::qi::unary_parser<complex_kwd_parser<Subject, KeywordType, LoopIter, Distinct > >
+ {
+ struct complex_kwd_parser_id;
+ typedef Subject subject_type;
+ typedef Distinct distinct;
+
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ typedef typename
+ traits::build_std_vector<
+ typename traits::attribute_of<
+ Subject, Context, Iterator>::type
+ >::type
+ type;
+ };
+
+
+ complex_kwd_parser(Subject const& subject
+ , typename add_reference<KeywordType>::type keyword
+ , LoopIter const& iter)
+ : subject(subject), iter(iter), keyword(keyword) {}
+
+ // Call the subject parser on a non container attribute
+ 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
+ {
+ return subject.parse(first,last,context,skipper,attr);
+ }
+
+ // Call the subject parser on a container attribute
+ 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_) const
+ {
+
+ // synthesized attribute needs to be default constructed
+ typename traits::container_value<Attribute>::type val =
+ typename traits::container_value<Attribute>::type();
+
+ Iterator save = first;
+ bool r = subject.parse(first,last,context,skipper, val);
+ if (r)
+ {
+ // push the parsed value into our attribute
+ r = traits::push_back(attr, val);
+ if (!r)
+ first = save;
+ }
+ return r;
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute,typename NoCasePass>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, skipper_keyword_marker<Skipper,NoCasePass> const& skipper
+ , Attribute &attr) const
+ {
+
+ typedef typename traits::attribute_of<
+ Subject, Context, Iterator>::type
+ subject_attribute;
+
+ typedef typename mpl::and_<
+ traits::is_container<Attribute>
+ , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
+ >::type predicate;
+
+ if(parse_impl(first,last,context,skipper.skipper,attr, predicate()))
+ return iter.register_successful_parse(skipper.flag,skipper.counter);
+ return false;
+ }
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr) const
+ {
+ typedef typename traits::attribute_of<
+ Subject, Context, Iterator>::type
+ subject_attribute;
+
+ typedef typename mpl::and_<
+ traits::is_container<Attribute>
+ , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
+ >::type predicate;
+
+
+ // Parse the keyword
+ bool flag = iter.flag_init();
+ int counter = 0;
+ Iterator save = first;
+ spirit::qi::skip_over(first, last, skipper);
+ if(keyword.parse(first,last,context,skipper,unused)){
+ if( !distinct::value || skipper.parse(first,last,unused,unused,unused)){
+ // Followed by the subject parser
+ spirit::qi::skip_over(first, last, skipper);
+ if(parse_impl(first,last,context,skipper,attr, predicate()))
+ {
+ return iter.register_successful_parse(flag,counter);
+ }
+ }
+ }
+ first = save;
+ return flag;
+ }
+
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ if(distinct::value)
+ return info("dkwd", subject.what(context));
+ else
+ return info("kwd", subject.what(context));
+ }
+
+ Subject subject;
+ LoopIter iter;
+
+ KeywordType keyword;
+ private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ complex_kwd_parser& operator= (complex_kwd_parser const&);
+
+ template <typename Iterator, typename Context, typename Skipper>
+ static spirit::qi::detail::fail_function<Iterator, Context, Skipper>
+ fail_function(
+ Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper)
+ {
+ return spirit::qi::detail::fail_function<Iterator, Context, Skipper>
+ (first, last, context, skipper);
+ }
+
+ };
+
}}}}
///////////////////////////////////////////////////////////////////////////////
@@ -386,177 +605,546 @@ namespace boost { namespace spirit { namespace qi
// Parser generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
+ template <typename T1, typename T2, typename Subject, typename Modifiers, typename Distinct, typename MakeDirectiveHelper>
+ struct make_directive_internal_2_args
+ {
+
+ // is the keyword a string keyword ?
+ typedef typename traits::is_string<T1> is_string_kwd_type;
+ // make the keyword type
+ typedef typename mpl::if_< is_string_kwd_type ,
+ T1 ,
+ typename result_of::compile<qi::domain, T1>::type
+ >::type keyword_type;
+
+ typedef typename add_const<keyword_type>::type const_keyword;
+ // select the pass iterator type
+ typedef typename MakeDirectiveHelper::iterator_type iterator_type;
+ // determine if a no case modifier applies to the context
+ typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
+ // Determine the full type of the kwd / complex_kwd directive
+ typedef typename
+ mpl::if_<
+ is_string_kwd_type,
+ repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case, Distinct >,
+ repository::qi::complex_kwd_parser<Subject, const_keyword, iterator_type, Distinct >
+ >::type result_type;
+
+ // Return a kwd parser object
+ template <typename Terminal>
+ result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::true_ ) const
+ {
+ typename spirit::detail::get_encoding<Modifiers,
+ spirit::char_encoding::standard>::type encoding;
+ return result_type(subject
+ ,MakeDirectiveHelper::make_iterator(term.args)
+ ,encoding
+ );
+ }
+ template <typename Terminal>
+ result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::false_ ) const
+ {
+ return result_type(subject
+ ,fusion::at_c<0>(term.args)
+ ,MakeDirectiveHelper::make_iterator(term.args)
+ );
+ }
+ template <typename Terminal>
+ result_type create_kwd(Terminal const &term, Subject const & subject, Modifiers const& modifiers, boost::mpl::true_ ) const
+ {
+ return create_kwd_string(term,subject,no_case());
+ }
+ // Return a complex_kwd parser object
+ template <typename Terminal>
+ result_type create_kwd(Terminal const &term , Subject const & subject, Modifiers const& modifiers, boost::mpl::false_ ) const
+ {
+ return result_type(subject
+ ,compile<qi::domain>(fusion::at_c<0>(term.args),modifiers)
+ ,MakeDirectiveHelper::make_iterator(term.args)
+ );
+ }
+ // Select which object type to return
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
+ {
+ return create_kwd(term, subject, modifiers, is_string_kwd_type());
+ }
+
+ };
+
// Directive kwd(key)[p]
+ template <typename T1, typename Subject, typename Modifiers, typename Distinct>
+ struct make_directive_internal
+ {
+ // is the keyword a string keyword ?
+ typedef typename traits::is_string<T1> is_string_kwd_type;
+ // make the keyword type
+ typedef typename mpl::if_< is_string_kwd_type ,
+ T1 ,
+ typename result_of::compile<qi::domain, T1, Modifiers>::type
+ >::type keyword_type;
+
+ typedef typename add_const<keyword_type>::type const_keyword;
+ // select the pass iterator type
+ typedef repository::qi::kwd_pass_iterator<int> iterator_type;
+ // determine if a no case modifier applies to the context
+ typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
+ // Determine the full type of the kwd / complex_kwd directive
+ typedef typename
+ mpl::if_<
+ is_string_kwd_type,
+ repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case, Distinct >,
+ repository::qi::complex_kwd_parser<Subject, const_keyword, iterator_type, Distinct>
+ >::type result_type;
+
+ // Return a kwd parser object
+ template <typename Terminal>
+ result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::true_) const
+ {
+ typename spirit::detail::get_encoding<Modifiers,
+ spirit::char_encoding::standard>::type encoding;
+
+ return result_type(subject
+ ,fusion::at_c<0>(term.args)
+ ,iterator_type()
+ ,encoding
+ );
+
+ }
+ template <typename Terminal>
+ result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::false_) const
+ {
+ return result_type(subject
+ ,fusion::at_c<0>(term.args)
+ ,iterator_type()
+ );
+ }
+ template <typename Terminal>
+ result_type create_kwd(Terminal const &term, Subject const & subject, Modifiers const& modifiers, boost::mpl::true_ ) const
+ {
+ return create_kwd_string(term,subject,no_case());
+ }
+ // Return a complex_kwd parser object
+ template <typename Terminal>
+ result_type create_kwd(Terminal const &term , Subject const & subject, Modifiers const& modifiers, boost::mpl::false_ ) const
+ {
+ return result_type(subject
+ ,compile<qi::domain>(fusion::at_c<0>(term.args),modifiers)
+ ,iterator_type()
+ );
+ }
+ // Select which object type to return
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers ) const
+ {
+ return create_kwd(term, subject, modifiers, is_string_kwd_type());
+ }
+ };
+
template <typename T1, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<repository::tag::kwd, fusion::vector1<T1> >, Subject, Modifiers>
{
+ typedef make_directive_internal<T1, Subject, Modifiers, mpl::false_> make_directive_type;
+ typedef typename make_directive_type::result_type result_type;
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
+ {
+
+ return make_directive_type()(term, subject, modifiers);
+ }
+
+ };
+
+ template <typename T1, typename Subject, typename Modifiers>
+ struct make_directive<
+ terminal_ex<repository::tag::dkwd, fusion::vector1<T1> >, Subject, Modifiers>
+ {
+ typedef make_directive_internal<T1, Subject, Modifiers, mpl::true_> make_directive_type;
+ typedef typename make_directive_type::result_type result_type;
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
+ {
+
+ return make_directive_type()(term, subject, modifiers);
+ }
+
+ };
+
+
+
+ // Directive ikwd(key)[p]
+ template <typename T1, typename Subject, typename Modifiers>
+ struct make_directive<
+ terminal_ex<repository::tag::ikwd, fusion::vector1<T1> >, Subject, Modifiers>
+ {
typedef typename add_const<T1>::type const_keyword;
typedef repository::qi::kwd_pass_iterator<int> iterator_type;
- typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
+ typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type;
- typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
-
template <typename Terminal>
result_type operator()(
Terminal const& term, Subject const& subject, unused_type) const
{
+ typename spirit::detail::get_encoding<Modifiers,
+ spirit::char_encoding::standard>::type encoding;
+
return result_type(subject
,fusion::at_c<0>(term.args)
,iterator_type()
+ ,encoding
);
}
};
- // Directive ikwd(key)[p]
template <typename T1, typename Subject, typename Modifiers>
struct make_directive<
- terminal_ex<repository::tag::ikwd, fusion::vector1<T1> >, Subject, Modifiers>
+ terminal_ex<repository::tag::idkwd, fusion::vector1<T1> >, Subject, Modifiers>
{
typedef typename add_const<T1>::type const_keyword;
typedef repository::qi::kwd_pass_iterator<int> iterator_type;
- typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
+ typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type;
template <typename Terminal>
result_type operator()(
Terminal const& term, Subject const& subject, unused_type) const
{
- /* typename spirit::detail::get_encoding<Modifiers,
- spirit::char_encoding::standard>::type encoding;*/
+ typename spirit::detail::get_encoding<Modifiers,
+ spirit::char_encoding::standard>::type encoding;
return result_type(subject
,fusion::at_c<0>(term.args)
,iterator_type()
+ ,encoding
);
}
};
// Directive kwd(key,exact)[p]
+ template <typename T>
+ struct make_exact_helper
+ {
+ typedef repository::qi::kwd_exact_iterator<T> iterator_type;
+ template<typename Args>
+ static iterator_type make_iterator(Args const& args)
+ {
+ return iterator_type(fusion::at_c<1>(args));
+ }
+ };
+
template <typename T1, typename T2, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<repository::tag::kwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
{
+ typedef make_directive_internal_2_args< T1
+ , T2
+ , Subject
+ , Modifiers
+ , mpl::false_
+ , make_exact_helper<T2>
+ > make_directive_type;
+ typedef typename make_directive_type::result_type result_type;
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
+ {
+
+ return make_directive_type()(term,subject, modifiers);
+ }
+
+ };
+
+ template <typename T1, typename T2, typename Subject, typename Modifiers>
+ struct make_directive<
+ terminal_ex<repository::tag::dkwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
+ {
+ typedef make_directive_internal_2_args< T1
+ , T2
+ , Subject
+ , Modifiers
+ , mpl::true_
+ , make_exact_helper<T2>
+ > make_directive_type;
+
+ typedef typename make_directive_type::result_type result_type;
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
+ {
+
+ return make_directive_type()(term, subject, modifiers);
+ }
+
+ };
+
+
+ // Directive ikwd(key,exact)[p]
+ template <typename T1, typename T2, typename Subject, typename Modifiers>
+ struct make_directive<
+ terminal_ex<repository::tag::ikwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
+ {
typedef typename add_const<T1>::type const_keyword;
typedef repository::qi::kwd_exact_iterator<T2> iterator_type;
- typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
- typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
+ typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type;
template <typename Terminal>
result_type operator()(
- Terminal const& term, Subject const& subject, unused_type) const
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
{
+ typename spirit::detail::get_encoding<Modifiers,
+ spirit::char_encoding::standard>::type encoding;
return result_type(subject
,fusion::at_c<0>(term.args)
,fusion::at_c<1>(term.args)
+ , encoding
);
}
};
- // Directive ikwd(key,exact)[p]
template <typename T1, typename T2, typename Subject, typename Modifiers>
struct make_directive<
- terminal_ex<repository::tag::ikwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
+ terminal_ex<repository::tag::idkwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
{
typedef typename add_const<T1>::type const_keyword;
typedef repository::qi::kwd_exact_iterator<T2> iterator_type;
- typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
+ typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type;
template <typename Terminal>
result_type operator()(
- Terminal const& term, Subject const& subject, unused_type) const
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
{
+ typename spirit::detail::get_encoding<Modifiers,
+ spirit::char_encoding::standard>::type encoding;
return result_type(subject
, fusion::at_c<0>(term.args)
, fusion::at_c<1>(term.args)
+ , encoding
);
}
};
+
// Directive kwd(min, max)[p]
+
+ template <typename T>
+ struct make_finite_helper
+ {
+ typedef repository::qi::kwd_finite_iterator<T> iterator_type;
+ template<typename Args>
+ static iterator_type make_iterator(Args const& args)
+ {
+ return iterator_type(fusion::at_c<1>(args),fusion::at_c<2>(args));
+ }
+
+ };
+
template <typename T1, typename T2, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<repository::tag::kwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
{
+ typedef make_directive_internal_2_args< T1
+ , T2
+ , Subject
+ , Modifiers
+ , mpl::false_
+ , make_finite_helper<T2>
+ > make_directive_type;
+
+
+ typedef typename make_directive_type::result_type result_type;
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
+ {
+
+ return make_directive_type()(term,subject, modifiers);
+ }
+
+ };
+
+ template <typename T1, typename T2, typename Subject, typename Modifiers>
+ struct make_directive<
+ terminal_ex<repository::tag::dkwd, fusion::vector3<T1,T2,T2> >, Subject, Modifiers>
+ {
+
+ typedef make_directive_internal_2_args< T1
+ , T2
+ , Subject
+ , Modifiers
+ , mpl::true_
+ , make_finite_helper<T2>
+ > make_directive_type;
+
+ typedef typename make_directive_type::result_type result_type;
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
+ {
+
+ return make_directive_type()(term,subject, modifiers);
+ }
+
+ };
+
+ // Directive ikwd(min, max)[p]
+ template <typename T1, typename T2, typename Subject, typename Modifiers>
+ struct make_directive<
+ terminal_ex<repository::tag::ikwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
+ {
typedef typename add_const<T1>::type const_keyword;
typedef repository::qi::kwd_finite_iterator<T2> iterator_type;
- typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
- typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
+ typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type;
template <typename Terminal>
result_type operator()(
Terminal const& term, Subject const& subject, unused_type) const
{
+
+ typename spirit::detail::get_encoding<Modifiers,
+ spirit::char_encoding::standard>::type encoding;
return result_type(subject, fusion::at_c<0>(term.args),
iterator_type(
fusion::at_c<1>(term.args)
, fusion::at_c<2>(term.args)
+ , encoding
)
);
}
};
- // Directive ikwd(min, max)[p]
template <typename T1, typename T2, typename Subject, typename Modifiers>
struct make_directive<
- terminal_ex<repository::tag::ikwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
+ terminal_ex<repository::tag::idkwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
{
typedef typename add_const<T1>::type const_keyword;
typedef repository::qi::kwd_finite_iterator<T2> iterator_type;
- typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
+ typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type;
template <typename Terminal>
result_type operator()(
Terminal const& term, Subject const& subject, unused_type) const
{
+ typename spirit::detail::get_encoding<Modifiers,
+ spirit::char_encoding::standard>::type encoding;
return result_type(subject, fusion::at_c<0>(term.args),
iterator_type(
fusion::at_c<1>(term.args)
, fusion::at_c<2>(term.args)
+ , encoding
)
);
}
};
+
// Directive kwd(min, inf)[p]
+
+ template <typename T>
+ struct make_infinite_helper
+ {
+ typedef repository::qi::kwd_infinite_iterator<T> iterator_type;
+ template<typename Args>
+ static iterator_type make_iterator(Args const& args)
+ {
+ return iterator_type(fusion::at_c<1>(args));
+ }
+
+ };
+
+
template <typename T1, typename T2, typename Subject, typename Modifiers>
struct make_directive<
- terminal_ex<repository::tag::kwd
+ terminal_ex<repository::tag::kwd, fusion::vector3<T1,T2,inf_type> >, Subject, Modifiers>
+ {
+ typedef make_directive_internal_2_args< T1
+ , T2
+ , Subject
+ , Modifiers
+ , mpl::false_
+ , make_infinite_helper<T2>
+ > make_directive_type;
+
+ typedef typename make_directive_type::result_type result_type;
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, unused_type) const
+ {
+
+ return make_directive_type()(term,subject, unused_type());
+ }
+
+ };
+
+ template <typename T1, typename T2, typename Subject, typename Modifiers>
+ struct make_directive<
+ terminal_ex<repository::tag::dkwd, fusion::vector3<T1,T2,inf_type> >, Subject, Modifiers>
+ {
+ typedef make_directive_internal_2_args< T1
+ , T2
+ , Subject
+ , Modifiers
+ , mpl::false_
+ , make_infinite_helper<T2>
+ > make_directive_type;
+
+ typedef typename make_directive_type::result_type result_type;
+ template <typename Terminal>
+ result_type operator()(
+ Terminal const& term, Subject const& subject, unused_type) const
+ {
+
+ return make_directive_type()(term,subject, unused_type());
+ }
+
+ };
+
+
+ // Directive ikwd(min, inf)[p]
+ template <typename T1, typename T2, typename Subject, typename Modifiers>
+ struct make_directive<
+ terminal_ex<repository::tag::ikwd
, fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers>
{
typedef typename add_const<T1>::type const_keyword;
typedef repository::qi::kwd_infinite_iterator<T2> iterator_type;
- typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
- typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
+ typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type;
template <typename Terminal>
result_type operator()(
Terminal const& term, Subject const& subject, unused_type) const
{
+ typename spirit::detail::get_encoding<Modifiers,
+ spirit::char_encoding::standard>::type encoding;
+
return result_type(subject
, fusion::at_c<0>(term.args)
, fusion::at_c<1>(term.args)
+ , encoding
);
}
};
- // Directive ikwd(min, inf)[p]
template <typename T1, typename T2, typename Subject, typename Modifiers>
struct make_directive<
- terminal_ex<repository::tag::ikwd
+ terminal_ex<repository::tag::idkwd
, fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers>
{
typedef typename add_const<T1>::type const_keyword;
typedef repository::qi::kwd_infinite_iterator<T2> iterator_type;
- typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
+ typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type;
template <typename Terminal>
result_type operator()(
@@ -568,6 +1156,7 @@ namespace boost { namespace spirit { namespace qi
return result_type(subject
, fusion::at_c<0>(term.args)
, fusion::at_c<1>(term.args)
+ , encoding
);
}
};
@@ -578,10 +1167,32 @@ namespace boost { namespace spirit { namespace qi
namespace boost { namespace spirit { namespace traits
{
template <typename Subject, typename KeywordType
- , typename LoopIter, typename NoCase >
+ , typename LoopIter, typename NoCase , typename Distinct>
struct has_semantic_action<
- repository::qi::kwd_parser< Subject, KeywordType, LoopIter, NoCase > >
+ repository::qi::kwd_parser< Subject, KeywordType, LoopIter, NoCase, Distinct > >
+ : unary_has_semantic_action<Subject> {};
+
+ template <typename Subject, typename KeywordType
+ , typename LoopIter, typename Distinct >
+ struct has_semantic_action<
+ repository::qi::complex_kwd_parser< Subject, KeywordType, LoopIter, Distinct > >
: unary_has_semantic_action<Subject> {};
+
+ template <typename Subject, typename KeywordType
+ , typename LoopIter, typename NoCase, typename Attribute, typename Context
+ , typename Iterator, typename Distinct>
+ struct handles_container<repository::qi::kwd_parser<Subject, KeywordType, LoopIter, NoCase, Distinct>, Attribute
+ , Context, Iterator>
+ : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+
+ template <typename Subject, typename KeywordType
+ , typename LoopIter
+ , typename Attribute, typename Context
+ , typename Iterator, typename Distinct>
+ struct handles_container<repository::qi::complex_kwd_parser<Subject, KeywordType, LoopIter, Distinct>, Attribute
+ , Context, Iterator>
+ : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+
}}}
#endif
diff --git a/boost/spirit/repository/home/qi/operator/detail/keywords.hpp b/boost/spirit/repository/home/qi/operator/detail/keywords.hpp
index 81e17715df..06836f7746 100644
--- a/boost/spirit/repository/home/qi/operator/detail/keywords.hpp
+++ b/boost/spirit/repository/home/qi/operator/detail/keywords.hpp
@@ -1,6 +1,5 @@
/*=============================================================================
- Copyright (c) 2001-2011 Joel de Guzman
- Copyright (c) 2011 Thomas Bernard
+ Copyright (c) 2011-2012 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)
@@ -11,39 +10,35 @@
#if defined(_MSC_VER)
#pragma once
#endif
-
+#include <boost/fusion/include/nview.hpp>
+#include <boost/spirit/home/qi/string/lit.hpp>
+#include <boost/fusion/include/at.hpp>
namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
-
- // This helper class enables jumping over intermediate directives
- // down the kwd parser iteration count checking policy
- struct register_successful_parse
- {
- template <typename Subject>
- static bool call(Subject const &subject,bool &flag, int &counter)
- {
- return subject.iter.register_successful_parse(flag,counter);
- }
- template <typename Subject, typename Action>
- static bool call(spirit::qi::action<Subject, Action> const &subject,bool &flag, int &counter)
- {
- return subject.subject.iter.register_successful_parse(flag,counter);
- }
- template <typename Subject>
- static bool call(spirit::qi::hold_directive<Subject> const &subject,bool &flag, int &counter)
- {
- return subject.subject.iter.register_successful_parse(flag,counter);
- }
- };
// 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 T>
+ struct is_distinct : T::distinct { };
+ template<typename T, typename Action>
+ struct is_distinct< spirit::qi::action<T,Action> > : T::distinct { };
+
+ template<typename T>
+ struct is_distinct< spirit::qi::hold_directive<T> > : T::distinct { };
+
+
+
template < typename Elements, typename Iterator ,typename Context ,typename Skipper
,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
- class parse_dispatcher
+ struct parse_dispatcher
: public boost::static_visitor<bool>
{
+
+ typedef Iterator iterator_type;
+ typedef Context context_type;
+ typedef Skipper skipper_type;
+ typedef Elements elements_type;
+
typedef typename add_reference<Attribute>::type attr_reference;
-
public:
parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper
@@ -65,7 +60,8 @@ namespace boost { namespace spirit { namespace repository { namespace qi { names
, Index& idx ) const
{
Iterator save = first;
- skipper_keyword_marker<Skipper,NoCasePass> marked_skipper(skipper,flags[Index::value],counters[Index::value]);
+ skipper_keyword_marker<Skipper,NoCasePass>
+ marked_skipper(skipper,flags[Index::value],counters[Index::value]);
if(subject.parse(first,last,context,marked_skipper,unused))
{
@@ -84,7 +80,8 @@ namespace boost { namespace spirit { namespace repository { namespace qi { names
{
Iterator save = first;
- skipper_keyword_marker<Skipper,NoCasePass> marked_skipper(skipper,flags[Index::value],counters[Index::value]);
+ skipper_keyword_marker<Skipper,NoCasePass>
+ marked_skipper(skipper,flags[Index::value],counters[Index::value]);
if(subject.parse(first,last,context,marked_skipper,fusion::at_c<Index::value>(attr)))
{
return true;
@@ -95,12 +92,28 @@ namespace boost { namespace spirit { namespace repository { namespace qi { names
// Handle unused attributes
template <typename T> bool call(T &idx, mpl::false_) const{
+
+ typedef typename mpl::at<Elements,T>::type ElementType;
+ if(
+ (!is_distinct<ElementType>::value)
+ || skipper.parse(first,last,unused,unused,unused)
+ ){
+ spirit::qi::skip_over(first, last, skipper);
return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
}
+ return false;
+ }
// Handle normal attributes
template <typename T> bool call(T &idx, mpl::true_) const{
+ typedef typename mpl::at<Elements,T>::type ElementType;
+ if(
+ (!is_distinct<ElementType>::value)
+ || skipper.parse(first,last,unused,unused,unused)
+ ){
return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
}
+ return false;
+ }
const Elements &elements;
Iterator &first;
@@ -111,7 +124,572 @@ namespace boost { namespace spirit { namespace repository { namespace qi { names
Counters &counters;
attr_reference attr;
};
+ // string keyword loop handler
+ template <typename Elements, typename StringKeywords, typename IndexList, typename FlagsType, typename Modifiers>
+ struct string_keywords
+ {
+ // Create a variant type to be able to store parser indexes in the embedded symbols parser
+ typedef typename
+ spirit::detail::as_variant<
+ IndexList >::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;
+ };
+ template <typename F, typename Element>
+ struct result<F(spirit::qi::hold_directive<Element>)>
+ {
+ 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< StringKeywords >::type char_types;
+ typedef typename get_keyword_char_type<
+ typename mpl::if_<
+ mpl::equal_to<
+ typename mpl::size < char_types >::type
+ , mpl::int_<0>
+ >
+ , mpl::vector< boost::spirit::standard::char_type >
+ , char_types >::type
+ >::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;
+ };
+ template <typename F, typename Element>
+ struct result<F(spirit::qi::hold_directive<Element>)>
+ {
+ 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< StringKeywords >::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<IndexList>::type nb_elements;
+ // Determine if all the kwd directive are case sensitive/insensitive
+ typedef typename mpl::and_<
+ typename mpl::greater< nb_elements, mpl::int_<0> >::type
+ , typename mpl::equal_to< ikwd_count, nb_elements>::type
+ >::type all_ikwd;
+
+ typedef typename mpl::and_<
+ typename mpl::greater< nb_elements, mpl::int_<0> >::type
+ , typename mpl::equal_to< kwd_count, nb_elements>::type
+ >::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
+ first_pass_filter_type;
+
+ typedef typename mpl::or_<
+ all_directives_of_same_type
+ , no_case_modifier
+ >::type requires_one_pass;
+
+
+ // Functor which adds all the keywords/subject parser indexes
+ // collected from the subject kwd directives to the keyword tst parser
+ struct keyword_entry_adder
+ {
+ typedef int result_type;
+
+ keyword_entry_adder(shared_ptr<keywords_type> lookup,FlagsType &flags, Elements &elements) :
+ lookup(lookup)
+ ,flags(flags)
+ ,elements(elements)
+ {}
+
+ template <typename T>
+ int operator()(const T &index) const
+ {
+ return call(fusion::at_c<T::value>(elements),index);
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call(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 T & parser, const Position position) const
+ {
+ // Make the keyword/parse index entry in the tst parser
+ lookup->add(
+ traits::get_begin<char_type>(get_string(parser.keyword)),
+ traits::get_end<char_type>(get_string(parser.keyword)),
+ 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;
+ }
+
+ template <typename T, typename Position>
+ int call( const spirit::qi::hold_directive<T> & 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 String, bool no_attribute>
+ const String & get_string(const boost::spirit::qi::literal_string<String,no_attribute> &parser) const
+ {
+ return parser.str;
+ }
+
+ template <typename String, bool no_attribute>
+ const typename boost::spirit::qi::no_case_literal_string<String,no_attribute>::string_type &
+ get_string(const boost::spirit::qi::no_case_literal_string<String,no_attribute> &parser) const
+ {
+ return parser.str_lo;
+ }
+
+
+
+ shared_ptr<keywords_type> lookup;
+ FlagsType & flags;
+ Elements &elements;
+ };
+
+ string_keywords(Elements &elements,FlagsType &flags_init) : lookup(new keywords_type())
+ {
+ // Loop through all the subject parsers to build the keyword parser symbol parser
+ IndexList indexes;
+ keyword_entry_adder f1(lookup,flags_init,elements);
+ fusion::for_each(indexes,f1);
+
+ }
+ template <typename Iterator,typename ParseVisitor, typename Skipper>
+ bool parse(
+ Iterator &first,
+ const Iterator &last,
+ const ParseVisitor &parse_visitor,
+ const Skipper &skipper) const
+ {
+ if(parser_index_type* val_ptr =
+ lookup->find(first,last,first_pass_filter_type()))
+ {
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ template <typename Iterator,typename ParseVisitor, typename NoCaseParseVisitor,typename Skipper>
+ bool parse(
+ Iterator &first,
+ const Iterator &last,
+ const ParseVisitor &parse_visitor,
+ const NoCaseParseVisitor &no_case_parse_visitor,
+ const Skipper &skipper) const
+ {
+ Iterator saved_first = first;
+ if(parser_index_type* val_ptr =
+ lookup->find(first,last,first_pass_filter_type()))
+ {
+ if(!apply_visitor(parse_visitor,*val_ptr)){
+ return false;
+ }
+ return true;
+ }
+ // Second pass case insensitive
+ else if(parser_index_type* val_ptr
+ = lookup->find(saved_first,last,nc_filter()))
+ {
+ first = saved_first;
+ if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+ shared_ptr<keywords_type> lookup;
+
+
+ };
+
+ struct empty_keywords_list
+ {
+ typedef mpl::true_ requires_one_pass;
+
+ empty_keywords_list()
+ {}
+ template<typename Elements>
+ empty_keywords_list(const Elements &)
+ {}
+
+ template<typename Elements, typename FlagsInit>
+ empty_keywords_list(const Elements &, const FlagsInit &)
+ {}
+
+ template <typename Iterator,typename ParseVisitor, typename NoCaseParseVisitor,typename Skipper>
+ bool parse(
+ Iterator &first,
+ const Iterator &last,
+ const ParseVisitor &parse_visitor,
+ const NoCaseParseVisitor &no_case_parse_visitor,
+ const Skipper &skipper) const
+ {
+ return false;
+ }
+
+ template <typename Iterator,typename ParseVisitor, typename Skipper>
+ bool parse(
+ Iterator &first,
+ const Iterator &last,
+ const ParseVisitor &parse_visitor,
+ const Skipper &skipper) const
+ {
+ return false;
+ }
+
+ template <typename ParseFunction>
+ bool parse( ParseFunction &function ) const
+ {
+ return false;
+ }
+ };
+
+ template<typename ComplexKeywords>
+ struct complex_keywords
+ {
+ // Functor which performs the flag initialization for the complex keyword parsers
+ template <typename FlagsType, typename Elements>
+ struct flag_init_value_setter
+ {
+ typedef int result_type;
+
+ flag_init_value_setter(Elements &elements,FlagsType &flags)
+ :flags(flags)
+ ,elements(elements)
+ {}
+
+ template <typename T>
+ int operator()(const T &index) const
+ {
+ return call(fusion::at_c<T::value>(elements),index);
+ }
+
+ template <typename T, typename Position, typename Action>
+ int call(const spirit::qi::action<T,Action> &parser, const Position position ) const
+ {
+ // 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 T & parser, const Position position) const
+ {
+ // Get the initial state of the flags array and store it in the flags initializer
+ flags[Position::value]=parser.iter.flag_init();
+ return 0;
+ }
+
+ template <typename T, typename Position>
+ int call( const spirit::qi::hold_directive<T> & parser, const Position position) const
+ {
+ // 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;
+ }
+
+ FlagsType & flags;
+ Elements &elements;
+ };
+
+ template <typename Elements, typename Flags>
+ complex_keywords(Elements &elements, Flags &flags)
+ {
+ flag_init_value_setter<Flags,Elements> flag_initializer(elements,flags);
+ fusion::for_each(complex_keywords_inst,flag_initializer);
+ }
+
+ template <typename ParseFunction>
+ bool parse( ParseFunction &function ) const
+ {
+ return fusion::any(complex_keywords_inst,function);
+ }
+
+ ComplexKeywords complex_keywords_inst;
+ };
+ // This helper class enables jumping over intermediate directives
+ // down the kwd parser iteration count checking policy
+ struct register_successful_parse
+ {
+ template <typename Subject>
+ static bool call(Subject const &subject,bool &flag, int &counter)
+ {
+ return subject.iter.register_successful_parse(flag,counter);
+ }
+ template <typename Subject, typename Action>
+ static bool call(spirit::qi::action<Subject, Action> const &subject,bool &flag, int &counter)
+ {
+ return subject.subject.iter.register_successful_parse(flag,counter);
+ }
+ template <typename Subject>
+ static bool call(spirit::qi::hold_directive<Subject> const &subject,bool &flag, int &counter)
+ {
+ return subject.subject.iter.register_successful_parse(flag,counter);
+ }
+ };
+
+ // This helper class enables jumping over intermediate directives
+ // down the kwd parser
+ struct extract_keyword
+ {
+ template <typename Subject>
+ static Subject const& call(Subject const &subject)
+ {
+ return subject;
+ }
+ template <typename Subject, typename Action>
+ static Subject const& call(spirit::qi::action<Subject, Action> const &subject)
+ {
+ return subject.subject;
+ }
+ template <typename Subject>
+ static Subject const& call(spirit::qi::hold_directive<Subject> const &subject)
+ {
+ return subject.subject;
+ }
+ };
+
+ template <typename ParseDispatcher>
+ struct complex_kwd_function
+ {
+ typedef typename ParseDispatcher::iterator_type Iterator;
+ typedef typename ParseDispatcher::context_type Context;
+ typedef typename ParseDispatcher::skipper_type Skipper;
+ complex_kwd_function(
+ Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper, ParseDispatcher &dispatcher)
+ : first(first)
+ , last(last)
+ , context(context)
+ , skipper(skipper)
+ , dispatcher(dispatcher)
+ {
+ }
+
+ template <typename Component>
+ bool operator()(Component const& component)
+ {
+ Iterator save = first;
+ if(
+ extract_keyword::call(
+ fusion::at_c<
+ Component::value
+ ,typename ParseDispatcher::elements_type
+ >(dispatcher.elements)
+ )
+ .keyword.parse(
+ first
+ ,last
+ ,context
+ ,skipper
+ ,unused)
+ )
+ {
+ if(!dispatcher(component)){
+ first = save;
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ Iterator& first;
+ Iterator const& last;
+ Context& context;
+ Skipper const& skipper;
+ ParseDispatcher const& dispatcher;
+
+ private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ complex_kwd_function& operator= (complex_kwd_function const&);
+ };
+
+
}}}}}
#endif
diff --git a/boost/spirit/repository/home/qi/operator/keywords.hpp b/boost/spirit/repository/home/qi/operator/keywords.hpp
index c32c55c7af..f0382371fa 100644
--- a/boost/spirit/repository/home/qi/operator/keywords.hpp
+++ b/boost/spirit/repository/home/qi/operator/keywords.hpp
@@ -1,6 +1,6 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
- Copyright (c) 2011 Thomas Bernard
+ Copyright (c) 2011-2012 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)
@@ -22,6 +22,7 @@
#include <boost/fusion/include/iter_fold.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/value_at.hpp>
+#include <boost/fusion/include/mpl.hpp>
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
#include <boost/array.hpp>
@@ -35,10 +36,14 @@
#include <boost/mpl/size.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/back_inserter.hpp>
+#include <boost/mpl/filter_view.hpp>
+#include <boost/fusion/include/zip_view.hpp>
+#include <boost/fusion/include/as_vector.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>
+#include <boost/fusion/include/any.hpp>
namespace boost { namespace spirit
@@ -62,6 +67,7 @@ namespace boost { namespace spirit { namespace repository { namespace qi
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(kwd_parser_id)
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(complex_kwd_parser_id)
}
@@ -76,6 +82,16 @@ namespace boost { namespace spirit { namespace repository { namespace qi
template <typename Subject>
struct is_kwd_parser<spirit::qi::hold_directive<Subject> > : detail::has_kwd_parser_id<Subject> {};
+ template <typename T>
+ struct is_complex_kwd_parser : detail::has_complex_kwd_parser_id<T> {};
+
+ template <typename Subject, typename Action>
+ struct is_complex_kwd_parser<spirit::qi::action<Subject,Action> > : detail::has_complex_kwd_parser_id<Subject> {};
+
+ template <typename Subject>
+ struct is_complex_kwd_parser<spirit::qi::hold_directive<Subject> > : detail::has_complex_kwd_parser_id<Subject> {};
+
+
// Keywords operator
template <typename Elements, typename Modifiers>
struct keywords : spirit::qi::nary_parser<keywords<Elements,Modifiers> >
@@ -101,10 +117,15 @@ namespace boost { namespace spirit { namespace repository { namespace qi
typedef typename mpl::count_if<
Elements,
mpl::not_<
+ mpl::or_<
is_kwd_parser<
mpl::_1
+ > ,
+ is_complex_kwd_parser<
+ mpl::_1
>
>
+ >
> non_kwd_subject_count;
/// If the assertion fails here then you probably forgot to wrap a
@@ -130,208 +151,38 @@ namespace boost { namespace spirit { namespace repository { namespace qi
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;
- };
- template <typename F, typename Element>
- struct result<F(spirit::qi::hold_directive<Element>)>
- {
- 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;
+ typedef typename mpl::copy<int_range, mpl::back_inserter<mpl::vector<> > >::type type;
- // 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;
+ // Build an index mpl vector
+ typedef typename build_parser_tags< Elements >::type parser_index_vector;
- /// Our symbols container
- typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
+ template <typename idx>
+ struct is_complex_kwd_parser_filter : is_complex_kwd_parser< typename mpl::at<Elements, idx>::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 idx>
+ struct is_kwd_parser_filter : is_kwd_parser< typename mpl::at<Elements, idx>::type >
+ {};
- template <typename F, typename Element>
- struct result<F(Element)>
- {
- typedef typename Element::no_case_keyword type;
+ // filter out the string kwd directives
+ typedef typename mpl::filter_view< Elements, is_kwd_parser<mpl_::_> >::type string_keywords;
- };
- template <typename F, typename Element,typename Action>
- struct result<F(spirit::qi::action<Element,Action>) >
- {
- typedef typename Element::no_case_keyword type;
- };
- template <typename F, typename Element>
- struct result<F(spirit::qi::hold_directive<Element>)>
- {
- typedef typename Element::no_case_keyword type;
- };
+ typedef typename mpl::filter_view< parser_index_vector ,
+ is_kwd_parser_filter< mpl::_ >
+ >::type string_keyword_indexes;
+ // filter out the complex keywords
+ typedef typename mpl::filter_view< parser_index_vector ,
+ is_complex_kwd_parser_filter< mpl::_ >
+ >::type complex_keywords_indexes;
- // never called, but needed for decltype-based result_of (C++0x)
- template <typename Element>
- typename result<element_case_type(Element)>::type
- operator()(Element&) const;
- };
+ //typedef typename fusion::filter_view< Elements, is_complex_kwd_parser< mpl::_ > > complex_keywords_view;
- // 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;
-
+ typename mpl::empty<complex_keywords_indexes>::type,
+ detail::empty_keywords_list,
+ detail::complex_keywords< complex_keywords_indexes >
+ >::type complex_keywords_type;
// build a bool array and an integer array which will be used to
// check that the repetition constraints of the kwd parsers are
@@ -339,91 +190,24 @@ namespace boost { namespace spirit { namespace repository { namespace qi
typedef boost::array<bool, fusion::result_of::size<Elements>::value> flags_type;
typedef boost::array<int, fusion::result_of::size<Elements>::value> counters_type;
+ typedef typename mpl::if_<
+ typename mpl::empty<string_keyword_indexes>::type,
+ detail::empty_keywords_list,
+ detail::string_keywords<
+ Elements,
+ string_keywords,
+ string_keyword_indexes,
+ flags_type,
+ Modifiers>
+ >::type string_keywords_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
+ keywords(Elements const& elements_) :
+ elements(elements_)
+ , string_keywords_inst(elements,flags_init)
+ , complex_keywords_inst(elements,flags_init)
{
- 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;
- }
-
- template <typename T, typename Position>
- int call( const int i, const spirit::qi::hold_directive<T> & 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;
- }
-
-
- 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
@@ -434,7 +218,7 @@ namespace boost { namespace spirit { namespace repository { namespace qi
// 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()
+ typename string_keywords_type::requires_one_pass()
);
}
@@ -442,7 +226,7 @@ namespace boost { namespace spirit { namespace repository { namespace qi
, typename Skipper, typename Attribute>
bool parse_impl(Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper
- , Attribute& attr_,mpl::true_ /* no ikwd */) const
+ , Attribute& attr_,mpl::true_ /* one pass */) const
{
// wrap the attribute in a tuple if it is not a tuple
@@ -458,10 +242,16 @@ namespace boost { namespace spirit { namespace repository { namespace qi
, 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);
+ typedef repository::qi::detail::complex_kwd_function< parser_visitor_type > complex_kwd_function_type;
+
+ complex_kwd_function_type
+ complex_function(first,last,context,skipper,parse_visitor);
+
// 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
@@ -471,35 +261,36 @@ namespace boost { namespace spirit { namespace repository { namespace qi
// 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()))
+ Iterator save = first;
+ if (string_keywords_inst.parse(first, last,parse_visitor,skipper))
{
- spirit::qi::skip_over(first, last, skipper);
- if(!apply_visitor(parse_visitor,*val_ptr)){
- first = save;
- return false;
- }
save = first;
}
- else
+ else {
+ // restore the position to the last successful keyword parse
+ first = save;
+ if(!complex_keywords_inst.parse(complex_function))
{
+ first = save;
// 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;
}
+ else
+ save = first;
}
+ }
return false;
}
@@ -508,7 +299,7 @@ namespace boost { namespace spirit { namespace repository { namespace qi
, typename Skipper, typename Attribute>
bool parse_impl(Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper
- , Attribute& attr_,mpl::false_) const
+ , Attribute& attr_,mpl::false_ /* two passes */) const
{
// wrap the attribute in a tuple if it is not a tuple
@@ -536,6 +327,12 @@ namespace boost { namespace spirit { namespace repository { namespace qi
no_case_parser_visitor_type no_case_parse_visitor(elements,first,last
,context,skipper,flags,counters,attr);
+ typedef repository::qi::detail::complex_kwd_function< parser_visitor_type > complex_kwd_function_type;
+
+ complex_kwd_function_type
+ complex_function(first,last,context,skipper,parse_visitor);
+
+
// 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
@@ -545,47 +342,37 @@ namespace boost { namespace spirit { namespace repository { namespace qi
// 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()))
+ Iterator save = first;
+ // String keywords pass
+ if (string_keywords_inst.parse(first,last,parse_visitor,no_case_parse_visitor,skipper))
{
- 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()))
+ else {
+ first = save;
+
+ if(!complex_keywords_inst.parse(complex_function))
{
- 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;
}
+ else
+ {
+ save = first;
+ }
+ }
}
return false;
}
@@ -600,7 +387,8 @@ namespace boost { namespace spirit { namespace repository { namespace qi
}
flags_type flags_init;
Elements elements;
- shared_ptr<keywords_type> lookup;
+ string_keywords_type string_keywords_inst;
+ complex_keywords_type complex_keywords_inst;
};
}}}}
@@ -634,6 +422,14 @@ namespace boost { namespace spirit { namespace traits
template <typename Elements, typename Modifiers>
struct has_semantic_action<repository::qi::keywords<Elements, Modifiers> >
: nary_has_semantic_action<Elements> {};
+
+ template <typename Elements, typename Attribute, typename Context
+ , typename Iterator, typename Modifiers>
+ struct handles_container<repository::qi::keywords<Elements,Modifiers>, Attribute
+ , Context, Iterator>
+ : nary_handles_container<Elements, Attribute, Context, Iterator> {};
+
+
}}}
#endif