diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
commit | 1a78a62555be32868418fe52f8e330c9d0f95d5a (patch) | |
tree | d3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/spirit/repository/home/qi | |
download | boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2 boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip |
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'boost/spirit/repository/home/qi')
-rw-r--r-- | boost/spirit/repository/home/qi/directive.hpp | 20 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/directive/confix.hpp | 150 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/directive/distinct.hpp | 143 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/directive/kwd.hpp | 588 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/directive/seek.hpp | 134 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/nonterminal.hpp | 18 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/nonterminal/subrule.hpp | 586 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/operator.hpp | 17 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/operator/detail/keywords.hpp | 117 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/operator/keywords.hpp | 640 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/primitive.hpp | 19 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/primitive/advance.hpp | 130 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/primitive/flush_multi_pass.hpp | 92 | ||||
-rw-r--r-- | boost/spirit/repository/home/qi/primitive/iter_pos.hpp | 83 |
14 files changed, 2737 insertions, 0 deletions
diff --git a/boost/spirit/repository/home/qi/directive.hpp b/boost/spirit/repository/home/qi/directive.hpp new file mode 100644 index 0000000000..4e21b11400 --- /dev/null +++ b/boost/spirit/repository/home/qi/directive.hpp @@ -0,0 +1,20 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// Copyright (c) 2001-2011 Joel de Guzman +// +// 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_REPOSITORY_QI_DIRECTIVE_APR_28_2009_1258PM) +#define SPIRIT_REPOSITORY_QI_DIRECTIVE_APR_28_2009_1258PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/repository/home/qi/directive/distinct.hpp> +#include <boost/spirit/repository/home/qi/directive/confix.hpp> +#include <boost/spirit/repository/home/qi/directive/kwd.hpp> +#include <boost/spirit/repository/home/qi/directive/seek.hpp> + +#endif + diff --git a/boost/spirit/repository/home/qi/directive/confix.hpp b/boost/spirit/repository/home/qi/directive/confix.hpp new file mode 100644 index 0000000000..d51b0011af --- /dev/null +++ b/boost/spirit/repository/home/qi/directive/confix.hpp @@ -0,0 +1,150 @@ +// Copyright (c) 2009 Chris Hoeppler +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_SPIRIT_REPOSITORY_QI_CONFIX_JUN_22_2009_1041AM) +#define BOOST_SPIRIT_REPOSITORY_QI_CONFIX_JUN_22_2009_1041AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/qi/domain.hpp> +#include <boost/spirit/home/qi/meta_compiler.hpp> +#include <boost/spirit/home/qi/auxiliary/lazy.hpp> +#include <boost/spirit/home/support/common_terminals.hpp> +#include <boost/spirit/home/support/info.hpp> +#include <boost/spirit/home/support/unused.hpp> +#include <boost/spirit/home/qi/detail/attributes.hpp> + +#include <boost/spirit/repository/home/support/confix.hpp> + +#include <boost/fusion/include/vector.hpp> +#include <boost/mpl/or.hpp> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit +{ + /////////////////////////////////////////////////////////////////////////// + // Enablers + /////////////////////////////////////////////////////////////////////////// + + // enables confix(..., ...)[] + template <typename Prefix, typename Suffix> + struct use_directive<qi::domain + , terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> > > + : mpl::true_ {}; + + // enables *lazy* confix(..., ...)[] + template <> + struct use_lazy_directive<qi::domain, repository::tag::confix, 2> + : mpl::true_ {}; + +}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace repository { namespace qi +{ + using repository::confix_type; + using repository::confix; + + /////////////////////////////////////////////////////////////////////////// + // the confix() generated parser + template <typename Subject, typename Prefix, typename Suffix> + struct confix_parser + : spirit::qi::unary_parser<confix_parser<Subject, Prefix, Suffix> > + { + typedef Subject subject_type; + + template <typename Context, typename Iterator> + struct attribute + : traits::attribute_of<subject_type, Context, Iterator> + {}; + + confix_parser(Subject const& subject, Prefix const& prefix + , Suffix const& suffix) + : subject(subject), prefix(prefix), suffix(suffix) {} + + template <typename Iterator, typename Context + , typename Skipper, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context& context, Skipper const& skipper + , Attribute& attr) const + { + Iterator iter = first; + + if (!(prefix.parse(iter, last, context, skipper, unused) && + subject.parse(iter, last, context, skipper, attr) && + suffix.parse(iter, last, context, skipper, unused))) + { + return false; + } + + first = iter; + return true; + } + + template <typename Context> + info what(Context const& ctx) const + { + return info("confix", subject.what(ctx)); + } + + Subject subject; + Prefix prefix; + Suffix suffix; + }; + +}}}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace qi +{ + /////////////////////////////////////////////////////////////////////////// + // Parser generators: make_xxx function (objects) + /////////////////////////////////////////////////////////////////////////// + + // creates confix(..., ...)[] directive + template <typename Prefix, typename Suffix, typename Subject + , typename Modifiers> + struct make_directive< + terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> > + , Subject, Modifiers> + { + typedef typename + result_of::compile<qi::domain, Prefix, Modifiers>::type + prefix_type; + typedef typename + result_of::compile<qi::domain, Suffix, Modifiers>::type + suffix_type; + + typedef repository::qi::confix_parser< + Subject, prefix_type, suffix_type> result_type; + + template <typename Terminal> + result_type operator()(Terminal const& term, Subject const& subject + , Modifiers const& modifiers) const + { + return result_type(subject + , compile<qi::domain>(fusion::at_c<0>(term.args), modifiers) + , compile<qi::domain>(fusion::at_c<1>(term.args), modifiers)); + } + }; + +}}} + +namespace boost { namespace spirit { namespace traits +{ + template <typename Subject, typename Prefix, typename Suffix> + struct has_semantic_action< + repository::qi::confix_parser<Subject, Prefix, Suffix> > + : mpl::or_< + has_semantic_action<Subject> + , has_semantic_action<Prefix> + , has_semantic_action<Suffix> + > {}; +}}} + +#endif + diff --git a/boost/spirit/repository/home/qi/directive/distinct.hpp b/boost/spirit/repository/home/qi/directive/distinct.hpp new file mode 100644 index 0000000000..740694559e --- /dev/null +++ b/boost/spirit/repository/home/qi/directive/distinct.hpp @@ -0,0 +1,143 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// Copyright (c) 2001-2011 Joel de Guzman +// Copyright (c) 2003 Vaclav Vesely +// +// 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_REPOSITORY_QI_DISTINCT_MAY_20_2009_0825M) +#define SPIRIT_REPOSITORY_QI_DISTINCT_MAY_20_2009_0825M + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/qi/skip_over.hpp> +#include <boost/spirit/home/qi/domain.hpp> +#include <boost/spirit/home/qi/parser.hpp> +#include <boost/spirit/home/qi/meta_compiler.hpp> +#include <boost/spirit/home/qi/detail/unused_skipper.hpp> +#include <boost/spirit/home/support/common_terminals.hpp> +#include <boost/spirit/home/support/make_component.hpp> +#include <boost/spirit/home/support/info.hpp> +#include <boost/spirit/home/support/unused.hpp> +#include <boost/spirit/home/qi/detail/attributes.hpp> +#include <boost/spirit/home/support/string_traits.hpp> +#include <boost/spirit/home/qi/auxiliary/eps.hpp> +#include <boost/spirit/home/qi/auxiliary/lazy.hpp> +#include <boost/spirit/home/qi/directive/lexeme.hpp> +#include <boost/spirit/home/qi/operator/not_predicate.hpp> + +#include <boost/spirit/repository/home/support/distinct.hpp> + +#include <boost/fusion/include/at.hpp> +#include <boost/fusion/include/vector.hpp> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit +{ + /////////////////////////////////////////////////////////////////////////// + // Enablers + /////////////////////////////////////////////////////////////////////////// + + // enables distinct(...)[...] + template <typename Tail> + struct use_directive<qi::domain + , terminal_ex<repository::tag::distinct, fusion::vector1<Tail> > > + : mpl::true_ {}; + + // enables *lazy* distinct(...)[...] + template <> + struct use_lazy_directive<qi::domain, repository::tag::distinct, 1> + : mpl::true_ {}; + +}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace repository {namespace qi +{ + using repository::distinct_type; + using repository::distinct; + + template <typename Subject, typename Tail, typename Modifier> + struct distinct_parser + : spirit::qi::unary_parser<distinct_parser<Subject, Tail, Modifier> > + { + template <typename Context, typename Iterator> + struct attribute + : traits::attribute_of<Subject, Context, Iterator> + {}; + + distinct_parser(Subject const& subject, Tail const& tail) + : subject(subject), tail(tail) {} + + template <typename Iterator, typename Context + , typename Skipper, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context& context, Skipper const& skipper, Attribute& attr) const + { + Iterator iter = first; + + spirit::qi::skip_over(iter, last, skipper); + if (!subject.parse(iter, last, context + , spirit::qi::detail::unused_skipper<Skipper>(skipper), attr)) + return false; + + Iterator i = iter; + if (tail.parse(i, last, context, unused, unused)) + return false; + + first = iter; + return true; + } + + template <typename Context> + info what(Context& /*ctx*/) const + { + return info("distinct"); + } + + Subject subject; + Tail tail; + }; + +}}}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace qi +{ + /////////////////////////////////////////////////////////////////////////// + // Parser generators: make_xxx function (objects) + /////////////////////////////////////////////////////////////////////////// + template <typename Tail, typename Subject, typename Modifiers> + struct make_directive< + terminal_ex<repository::tag::distinct, fusion::vector1<Tail> > + , Subject, Modifiers> + { + typedef typename result_of::compile<qi::domain, Tail, Modifiers>::type + tail_type; + + typedef repository::qi::distinct_parser< + Subject, tail_type, Modifiers> result_type; + + template <typename Terminal> + result_type operator()(Terminal const& term, Subject const& subject + , Modifiers const& modifiers) const + { + return result_type(subject + , compile<qi::domain>(fusion::at_c<0>(term.args), modifiers)); + } + }; + +}}} + +namespace boost { namespace spirit { namespace traits +{ + template <typename Subject, typename Tail, typename Modifier> + struct has_semantic_action< + repository::qi::distinct_parser<Subject, Tail, Modifier> > + : unary_has_semantic_action<Subject> {}; +}}} + +#endif + diff --git a/boost/spirit/repository/home/qi/directive/kwd.hpp b/boost/spirit/repository/home/qi/directive/kwd.hpp new file mode 100644 index 0000000000..79fdc2f6dc --- /dev/null +++ b/boost/spirit/repository/home/qi/directive/kwd.hpp @@ -0,0 +1,588 @@ +/*============================================================================= + 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_KWD_NOVEMBER_14_2008_1148AM) +#define SPIRIT_KWD_NOVEMBER_14_2008_1148AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/qi/meta_compiler.hpp> +#include <boost/spirit/home/qi/parser.hpp> +#include <boost/spirit/home/qi/auxiliary/lazy.hpp> +#include <boost/spirit/home/qi/operator/kleene.hpp> +#include <boost/spirit/home/support/container.hpp> +#include <boost/spirit/home/qi/detail/attributes.hpp> +#include <boost/spirit/home/qi/detail/fail_function.hpp> +#include <boost/spirit/home/support/info.hpp> +#include <boost/spirit/repository/home/support/kwd.hpp> +#include <boost/fusion/include/at.hpp> +#include <boost/foreach.hpp> +#include <vector> + +namespace boost { namespace spirit +{ + /////////////////////////////////////////////////////////////////////////// + // Enablers + /////////////////////////////////////////////////////////////////////////// + + template < typename T> + struct use_directive<qi::domain + , terminal_ex<repository::tag::kwd // enables kwd(key)[p] + , fusion::vector1<T > > + > : traits::is_string<T> {}; + + template < typename T> + struct use_directive<qi::domain + , terminal_ex<repository::tag::ikwd // enables ikwd(key)[p] + , fusion::vector1<T > > + > : traits::is_string<T> {}; + + + 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> {}; + + 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> {}; + + 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> {}; + + 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> {}; + + 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> {}; + + 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> {}; + + + /* template <> // enables *lazy* kwd(exact)[p] + struct use_lazy_directive< + qi::domain + , tag::kwd + , 1 // arity + > : mpl::true_ {}; + + template <> // enables *lazy* kwd(min, max)[p] + struct use_lazy_directive< // and kwd(min, inf)[p] + qi::domain + , tag::kwd + , 2 // arity + > : mpl::true_ {}; +*/ + +}} + +namespace boost { namespace spirit { namespace repository { namespace qi +{ + using repository::kwd; + using repository::ikwd; + using spirit::inf; + using spirit::inf_type; + +template <typename T> + struct kwd_pass_iterator // handles kwd(exact)[p] + { + kwd_pass_iterator() {} + bool flag_init() const { return true; } + bool register_successful_parse(bool &flag,T &i) const { + flag=true; + return true; + } + + + private: + // silence MSVC warning C4512: assignment operator could not be generated + kwd_pass_iterator& operator= (kwd_pass_iterator const&); + }; + + template <typename T> + struct kwd_exact_iterator // handles kwd(exact)[p] + { + kwd_exact_iterator(T const exact) + : exact(exact){} + + typedef T type; + bool flag_init() const { return false; } + bool register_successful_parse(bool &flag,T &i) const { + i++; + if(i<exact) + { + flag=false; + return true; + } + else if(i==exact) + { + flag=true; + return true; + } + else + return flag=false; + + } + T const exact; + + private: + // silence MSVC warning C4512: assignment operator could not be generated + kwd_exact_iterator& operator= (kwd_exact_iterator const&); + }; + + template <typename T> + struct kwd_finite_iterator // handles kwd(min, max)[p] + { + kwd_finite_iterator(T const min, T const max) + : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) + , max BOOST_PREVENT_MACRO_SUBSTITUTION (max) + {} + + typedef T type; + bool flag_init() const { return min==0; } + bool register_successful_parse(bool &flag,T &i) const { + i++; + if(i<min) + { + flag=false; + return true; + } + else if(i>=min && i<=max) + { + return flag=true; + } + else + return flag=false; + } + T const min; + T const max; + + private: + // silence MSVC warning C4512: assignment operator could not be generated + kwd_finite_iterator& operator= (kwd_finite_iterator const&); + }; + + template <typename T> + struct kwd_infinite_iterator // handles kwd(min, inf)[p] + { + kwd_infinite_iterator(T const min) + : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) {} + + typedef T type; + bool flag_init() const { return min==0; } + bool register_successful_parse(bool &flag,T &i) const { + i++; + flag = i>=min; + return true; + } + T const min; + + private: + // silence MSVC warning C4512: assignment operator could not be generated + kwd_infinite_iterator& operator= (kwd_infinite_iterator const&); + }; + + // This class enables the transportation of parameters needed to call + // the occurence constraint checker from higher level calls + // It also serves to select the correct parse function call + // of the keyword parser. The implementation changes depending if it is + // called form a keyword parsing loop or not. + template <typename Skipper, typename NoCasePass> + struct skipper_keyword_marker + { + typedef NoCasePass no_case_pass; + + skipper_keyword_marker(Skipper const &skipper,bool &flag,int &counter) : + skipper(skipper) + , flag(flag) + , counter(counter) + {} + + const Skipper &skipper; + bool &flag; + int &counter; + }; + + template <typename Subject, typename KeywordType, typename LoopIter , typename NoCase > + struct kwd_parser : spirit::qi::unary_parser<kwd_parser<Subject, KeywordType, LoopIter , NoCase > > + { + struct kwd_parser_id; + + typedef Subject subject_type; + typedef NoCase no_case_keyword; + + typedef typename + remove_const<typename traits::char_type_of<KeywordType>::type>::type + char_type; + + typedef std::basic_string<char_type> keyword_type; + + template <typename Context, typename Iterator> + struct attribute + { + typedef typename + traits::build_std_vector< + typename traits::attribute_of< + Subject, Context, Iterator>::type + >::type + type; + }; + + + 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((no_case_keyword::value && NoCasePass::value) || !NoCasePass::value) + { + 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)){ + // 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(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; + private: + // silence MSVC warning C4512: assignment operator could not be generated + kwd_parser& operator= (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); + } + + + }; +}}}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace qi +{ + + /////////////////////////////////////////////////////////////////////////// + // Parser generators: make_xxx function (objects) + /////////////////////////////////////////////////////////////////////////// + + // Directive kwd(key)[p] + template <typename T1, typename Subject, typename Modifiers> + struct make_directive< + terminal_ex<repository::tag::kwd, 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, no_case > result_type; + + template <typename Terminal> + result_type operator()( + Terminal const& term, Subject const& subject, unused_type) const + { + return result_type(subject + ,fusion::at_c<0>(term.args) + ,iterator_type() + ); + } + }; + + // 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 repository::qi::kwd_parser<Subject, const_keyword, iterator_type, 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() + ); + } + }; + + // Directive kwd(key,exact)[p] + template <typename T1, typename T2, typename Subject, typename Modifiers> + struct make_directive< + terminal_ex<repository::tag::kwd, 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; + + template <typename Terminal> + result_type operator()( + Terminal const& term, Subject const& subject, unused_type) const + { + return result_type(subject + ,fusion::at_c<0>(term.args) + ,fusion::at_c<1>(term.args) + ); + } + }; + + // 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 repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type; + + template <typename Terminal> + result_type operator()( + Terminal const& term, Subject const& subject, unused_type) const + { + return result_type(subject + , fusion::at_c<0>(term.args) + , fusion::at_c<1>(term.args) + ); + } + }; + + // Directive kwd(min, max)[p] + 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 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; + + template <typename Terminal> + result_type operator()( + Terminal const& term, Subject const& subject, unused_type) const + { + return result_type(subject, fusion::at_c<0>(term.args), + iterator_type( + fusion::at_c<1>(term.args) + , fusion::at_c<2>(term.args) + ) + ); + } + }; + + // 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 repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type; + + template <typename Terminal> + result_type operator()( + Terminal const& term, Subject const& subject, unused_type) const + { + + return result_type(subject, fusion::at_c<0>(term.args), + iterator_type( + fusion::at_c<1>(term.args) + , fusion::at_c<2>(term.args) + ) + ); + } + }; + + // Directive kwd(min, inf)[p] + template <typename T1, typename T2, typename Subject, typename Modifiers> + struct make_directive< + terminal_ex<repository::tag::kwd + , 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; + + template <typename Terminal> + result_type operator()( + Terminal const& term, Subject const& subject, unused_type) const + { + return result_type(subject + , fusion::at_c<0>(term.args) + , fusion::at_c<1>(term.args) + ); + } + }; + + // 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 repository::qi::kwd_parser<Subject, const_keyword, iterator_type, 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) + , fusion::at_c<1>(term.args) + ); + } + }; + + +}}} + +namespace boost { namespace spirit { namespace traits +{ + template <typename Subject, typename KeywordType + , typename LoopIter, typename NoCase > + struct has_semantic_action< + repository::qi::kwd_parser< Subject, KeywordType, LoopIter, NoCase > > + : unary_has_semantic_action<Subject> {}; +}}} + +#endif + diff --git a/boost/spirit/repository/home/qi/directive/seek.hpp b/boost/spirit/repository/home/qi/directive/seek.hpp new file mode 100644 index 0000000000..951a337cbe --- /dev/null +++ b/boost/spirit/repository/home/qi/directive/seek.hpp @@ -0,0 +1,134 @@ +/*////////////////////////////////////////////////////////////////////////////// + Copyright (c) 2011 Jamboree + + 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_REPOSITORY_QI_SEEK +#define BOOST_SPIRIT_REPOSITORY_QI_SEEK + + +#if defined(_MSC_VER) +#pragma once +#endif + + +#include <boost/spirit/home/qi/meta_compiler.hpp> +#include <boost/spirit/home/qi/parser.hpp> +#include <boost/spirit/home/qi/detail/attributes.hpp> +#include <boost/spirit/home/support/info.hpp> +#include <boost/spirit/home/support/unused.hpp> +#include <boost/spirit/home/support/has_semantic_action.hpp> +#include <boost/spirit/home/support/handles_container.hpp> +#include <boost/spirit/repository/home/support/seek.hpp> + + +namespace boost { namespace spirit +{ + /////////////////////////////////////////////////////////////////////////// + // Enablers + /////////////////////////////////////////////////////////////////////////// + + // enables seek[...] + template <> + struct use_directive<qi::domain, repository::tag::seek> + : mpl::true_ {}; +}} // namespace boost::spirit + + +namespace boost { namespace spirit { namespace repository {namespace qi +{ +#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS + using repository::seek; +#endif + using repository::seek_type; + + template <typename Subject> + struct seek_directive + : spirit::qi::unary_parser<seek_directive<Subject> > + { + typedef Subject subject_type; + + template <typename Context, typename Iterator> + struct attribute + { + typedef typename + traits::attribute_of<subject_type, Context, Iterator>::type + type; + }; + + seek_directive(Subject const& subject) + : subject(subject) + {} + + template + < + typename Iterator, typename Context + , typename Skipper, typename Attribute + > + bool parse + ( + Iterator& first, Iterator const& last + , Context& context, Skipper const& skipper + , Attribute& attr + ) const + { + for (Iterator it(first); ; ++it) + { + if (subject.parse(it, last, context, skipper, attr)) + { + first = it; + return true; + } + // fail only after subject fails & no input + if (it == last) + return false; + } + } + + template <typename Context> + info what(Context& context) const + { + return info("seek", subject.what(context)); + } + + Subject subject; + }; +}}}} // namespace boost::spirit::repository::qi + + +namespace boost { namespace spirit { namespace qi +{ + /////////////////////////////////////////////////////////////////////////// + // Parser generators: make_xxx function (objects) + /////////////////////////////////////////////////////////////////////////// + template <typename Subject, typename Modifiers> + struct make_directive<repository::tag::seek, Subject, Modifiers> + { + typedef repository::qi::seek_directive<Subject> result_type; + + result_type operator()(unused_type, Subject const& subject, unused_type) const + { + return result_type(subject); + } + }; +}}} // namespace boost::spirit::qi + + +namespace boost { namespace spirit { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + template <typename Subject> + struct has_semantic_action<repository::qi::seek_directive<Subject> > + : unary_has_semantic_action<Subject> {}; + + /////////////////////////////////////////////////////////////////////////// + template <typename Subject, typename Attribute, typename Context + , typename Iterator> + struct handles_container<repository::qi::seek_directive<Subject>, Attribute + , Context, Iterator> + : unary_handles_container<Subject, Attribute, Context, Iterator> {}; +}}} // namespace boost::spirit::traits + + +#endif diff --git a/boost/spirit/repository/home/qi/nonterminal.hpp b/boost/spirit/repository/home/qi/nonterminal.hpp new file mode 100644 index 0000000000..6b2dbb8fcb --- /dev/null +++ b/boost/spirit/repository/home/qi/nonterminal.hpp @@ -0,0 +1,18 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// Copyright (c) 2001-2011 Joel de Guzman +// Copyright (c) 2009 Francois Barel +// +// 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_REPOSITORY_QI_NONTERMINAL_AUG_12_2009_1140AM) +#define SPIRIT_REPOSITORY_QI_NONTERMINAL_AUG_12_2009_1140AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/repository/home/qi/nonterminal/subrule.hpp> + +#endif + diff --git a/boost/spirit/repository/home/qi/nonterminal/subrule.hpp b/boost/spirit/repository/home/qi/nonterminal/subrule.hpp new file mode 100644 index 0000000000..a2db38496b --- /dev/null +++ b/boost/spirit/repository/home/qi/nonterminal/subrule.hpp @@ -0,0 +1,586 @@ +/*============================================================================= + Copyright (c) 2009 Francois Barel + Copyright (c) 2001-2011 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_SPIRIT_REPOSITORY_QI_SUBRULE_AUGUST_06_2009_0239AM) +#define BOOST_SPIRIT_REPOSITORY_QI_SUBRULE_AUGUST_06_2009_0239AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/qi/domain.hpp> +#include <boost/spirit/home/qi/meta_compiler.hpp> +#include <boost/spirit/home/qi/parser.hpp> +#include <boost/spirit/home/qi/reference.hpp> +#include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp> +#include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp> +#include <boost/spirit/home/support/argument.hpp> +#include <boost/spirit/home/support/assert_msg.hpp> +#include <boost/spirit/home/qi/detail/attributes.hpp> +#include <boost/spirit/home/support/info.hpp> +#include <boost/spirit/home/support/unused.hpp> +#include <boost/spirit/home/support/nonterminal/extract_param.hpp> +#include <boost/spirit/home/support/nonterminal/locals.hpp> +#include <boost/spirit/repository/home/support/subrule_context.hpp> + +#include <boost/fusion/include/as_map.hpp> +#include <boost/fusion/include/at_key.hpp> +#include <boost/fusion/include/cons.hpp> +#include <boost/fusion/include/front.hpp> +#include <boost/fusion/include/has_key.hpp> +#include <boost/fusion/include/join.hpp> +#include <boost/fusion/include/make_map.hpp> +#include <boost/fusion/include/make_vector.hpp> +#include <boost/fusion/include/size.hpp> +#include <boost/fusion/include/vector.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/int.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/type_traits/add_reference.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/remove_reference.hpp> + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace repository { namespace qi +{ + /////////////////////////////////////////////////////////////////////////// + // subrule_group: + // - parser representing a group of subrule definitions (one or more), + // invokes first subrule on entry, + // - also a Proto terminal, so that a group behaves like any Spirit + // expression. + /////////////////////////////////////////////////////////////////////////// + template <typename Defs> + struct subrule_group + : proto::extends< + typename proto::terminal< + spirit::qi::reference<subrule_group<Defs> const> + >::type + , subrule_group<Defs> + > + , spirit::qi::parser<subrule_group<Defs> > + { + // Fusion associative sequence, associating each subrule ID in this + // group (as an MPL integral constant) with its definition + typedef Defs defs_type; + + typedef subrule_group<Defs> this_type; + typedef spirit::qi::reference<this_type const> reference_; + typedef typename proto::terminal<reference_>::type terminal; + typedef proto::extends<terminal, this_type> base_type; + + static size_t const params_size = + // Forward to first subrule. + remove_reference< + typename fusion::result_of::front<Defs>::type + >::type::second_type::params_size; + + subrule_group(subrule_group const& rhs) + : base_type(terminal::make(reference_(*this))) + , defs(rhs.defs) + { + } + + explicit subrule_group(Defs const& defs) + : base_type(terminal::make(reference_(*this))) + , defs(defs) + { + } + + // from a subrule ID, get the type of a reference to its definition + template <int ID> + struct def_type + { + typedef mpl::int_<ID> id_type; + + // If you are seeing a compilation error here, you are trying + // to use a subrule which was not defined in this group. + BOOST_SPIRIT_ASSERT_MSG( + (fusion::result_of::has_key< + defs_type const, id_type>::type::value) + , subrule_used_without_being_defined, (mpl::int_<ID>)); + + typedef typename + fusion::result_of::at_key<defs_type const, id_type>::type + type; + }; + + // from a subrule ID, get a reference to its definition + template <int ID> + typename def_type<ID>::type def() const + { + return fusion::at_key<mpl::int_<ID> >(defs); + } + + template <typename Context, typename Iterator> + struct attribute + // Forward to first subrule. + : mpl::identity< + typename remove_reference< + typename fusion::result_of::front<Defs>::type + >::type::second_type::attr_type> {}; + + template <typename Iterator, typename Context + , typename Skipper, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context& context, Skipper const& skipper + , Attribute& attr) const + { + // Forward to first subrule. + return parse_subrule(fusion::front(defs).second + , first, last, context, skipper, attr); + } + + template <typename Iterator, typename Context + , typename Skipper, typename Attribute, typename Params> + bool parse(Iterator& first, Iterator const& last + , Context& context, Skipper const& skipper + , Attribute& attr, Params const& params) const + { + // Forward to first subrule. + return parse_subrule(fusion::front(defs).second + , first, last, context, skipper, attr, params); + } + + template <int ID, typename Iterator, typename Context + , typename Skipper, typename Attribute> + bool parse_subrule_id(Iterator& first, Iterator const& last + , Context& context, Skipper const& skipper + , Attribute& attr) const + { + return parse_subrule(def<ID>() + , first, last, context, skipper, attr); + } + + template <int ID, typename Iterator, typename Context + , typename Skipper, typename Attribute, typename Params> + bool parse_subrule_id(Iterator& first, Iterator const& last + , Context& context, Skipper const& skipper + , Attribute& attr, Params const& params) const + { + return parse_subrule(def<ID>() + , first, last, context, skipper, attr, params); + } + + template <typename Def + , typename Iterator, typename Context + , typename Skipper, typename Attribute> + bool parse_subrule(Def const& def + , Iterator& first, Iterator const& last + , Context& /*caller_context*/, Skipper const& skipper + , Attribute& attr) const + { + // compute context type for this subrule + typedef typename Def::locals_type subrule_locals_type; + typedef typename Def::attr_type subrule_attr_type; + typedef typename Def::attr_reference_type subrule_attr_reference_type; + typedef typename Def::parameter_types subrule_parameter_types; + + typedef + subrule_context< + this_type + , fusion::cons< + subrule_attr_reference_type, subrule_parameter_types> + , subrule_locals_type + > + context_type; + + // prepare attribute + typedef traits::make_attribute< + subrule_attr_type, Attribute> make_attribute; + + // do down-stream transformation, provides attribute for + // rhs parser + typedef traits::transform_attribute< + typename make_attribute::type, subrule_attr_type, spirit::qi::domain> + transform; + + typename make_attribute::type made_attr = make_attribute::call(attr); + typename transform::type attr_ = transform::pre(made_attr); + + // If you are seeing a compilation error here, you are probably + // trying to use a subrule which has inherited attributes, + // without passing values for them. + context_type context(*this, attr_); + + if (def.binder(first, last, context, skipper)) + { + // do up-stream transformation, this integrates the results + // back into the original attribute value, if appropriate + traits::post_transform(attr, attr_); + return true; + } + + // inform attribute transformation of failed rhs + traits::fail_transform(attr, attr_); + return false; + } + + template <typename Def + , typename Iterator, typename Context + , typename Skipper, typename Attribute, typename Params> + bool parse_subrule(Def const& def + , Iterator& first, Iterator const& last + , Context& caller_context, Skipper const& skipper + , Attribute& attr, Params const& params) const + { + // compute context type for this subrule + typedef typename Def::locals_type subrule_locals_type; + typedef typename Def::attr_type subrule_attr_type; + typedef typename Def::attr_reference_type subrule_attr_reference_type; + typedef typename Def::parameter_types subrule_parameter_types; + + typedef + subrule_context< + this_type + , fusion::cons< + subrule_attr_reference_type, subrule_parameter_types> + , subrule_locals_type + > + context_type; + + // prepare attribute + typedef traits::make_attribute< + subrule_attr_type, Attribute> make_attribute; + + // do down-stream transformation, provides attribute for + // rhs parser + typedef traits::transform_attribute< + typename make_attribute::type, subrule_attr_type, spirit::qi::domain> + transform; + + typename make_attribute::type made_attr = make_attribute::call(attr); + typename transform::type attr_ = transform::pre(made_attr); + + // If you are seeing a compilation error here, you are probably + // trying to use a subrule which has inherited attributes, + // passing values of incompatible types for them. + context_type context(*this, attr_, params, caller_context); + + if (def.binder(first, last, context, skipper)) + { + // do up-stream transformation, this integrates the results + // back into the original attribute value, if appropriate + traits::post_transform(attr, attr_); + return true; + } + + // inform attribute transformation of failed rhs + traits::fail_transform(attr, attr_); + return false; + } + + template <typename Context> + info what(Context& context) const + { + // Forward to first subrule. + return fusion::front(defs).second.binder.p.what(context); + } + + template <typename Defs2> + subrule_group< + typename fusion::result_of::as_map< + typename fusion::result_of::join< + Defs const, Defs2 const>::type>::type> + operator,(subrule_group<Defs2> const& other) const + { + typedef subrule_group< + typename fusion::result_of::as_map< + typename fusion::result_of::join< + Defs const, Defs2 const>::type>::type> result_type; + return result_type(fusion::as_map(fusion::join(defs, other.defs))); + } + + // bring in the operator() overloads + this_type const& get_parameterized_subject() const { return *this; } + typedef this_type parameterized_subject_type; + #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp> + + Defs defs; + }; + + /////////////////////////////////////////////////////////////////////////// + // subrule_definition: holds one particular definition of a subrule + /////////////////////////////////////////////////////////////////////////// + template < + int ID_ + , typename Locals + , typename Attr + , typename AttrRef + , typename Parameters + , size_t ParamsSize + , typename Subject + , bool Auto_ + > + struct subrule_definition + { + typedef mpl::int_<ID_> id_type; + BOOST_STATIC_CONSTANT(int, ID = ID_); + + typedef Locals locals_type; + typedef Attr attr_type; + typedef AttrRef attr_reference_type; + typedef Parameters parameter_types; + static size_t const params_size = ParamsSize; + + typedef Subject subject_type; + typedef mpl::bool_<Auto_> auto_type; + BOOST_STATIC_CONSTANT(bool, Auto = Auto_); + + typedef spirit::qi::detail::parser_binder< + Subject, auto_type> binder_type; + + subrule_definition(Subject const& subject, std::string const& name) + : binder(subject), name(name) + { + } + + binder_type const binder; + std::string const name; + }; + + /////////////////////////////////////////////////////////////////////////// + // subrule placeholder: + // - on subrule definition: helper for creation of subrule_group, + // - on subrule invocation: Proto terminal and parser. + /////////////////////////////////////////////////////////////////////////// + template < + int ID_ + , typename T1 = unused_type + , typename T2 = unused_type + > + struct subrule + : proto::extends< + typename proto::terminal< + spirit::qi::reference<subrule<ID_, T1, T2> const> + >::type + , subrule<ID_, T1, T2> + > + , spirit::qi::parser<subrule<ID_, T1, T2> > + { + typedef mpl::int_<ID_> id_type; + BOOST_STATIC_CONSTANT(int, ID = ID_); + + typedef subrule<ID_, T1, T2> this_type; + typedef spirit::qi::reference<this_type const> reference_; + typedef typename proto::terminal<reference_>::type terminal; + typedef proto::extends<terminal, this_type> base_type; + + typedef mpl::vector<T1, T2> template_params; + + // locals_type is a sequence of types to be used as local variables + typedef typename + spirit::detail::extract_locals<template_params>::type + locals_type; + + typedef typename + spirit::detail::extract_sig<template_params>::type + sig_type; + + // This is the subrule's attribute type + typedef typename + spirit::detail::attr_from_sig<sig_type>::type + attr_type; + typedef typename add_reference<attr_type>::type attr_reference_type; + + // parameter_types is a sequence of types passed as parameters to the subrule + typedef typename + spirit::detail::params_from_sig<sig_type>::type + parameter_types; + + static size_t const params_size = + fusion::result_of::size<parameter_types>::type::value; + + explicit subrule(std::string const& name_ = "unnamed-subrule") + : base_type(terminal::make(reference_(*this))) + , name_(name_) + { + } + + // compute type of this subrule's definition for expr type Expr + template <typename Expr, bool Auto> + struct def_type_helper + { + // Report invalid expression error as early as possible. + // If you got an error_invalid_expression error message here, + // then the expression (Expr) is not a valid spirit qi expression. + BOOST_SPIRIT_ASSERT_MATCH(spirit::qi::domain, Expr); + + typedef typename result_of::compile< + spirit::qi::domain, Expr>::type subject_type; + + typedef subrule_definition< + ID_ + , locals_type + , attr_type + , attr_reference_type + , parameter_types + , params_size + , subject_type + , Auto + > const type; + }; + + // compute type of subrule group containing only this + // subrule's definition for expr type Expr + template <typename Expr, bool Auto> + struct group_type_helper + { + typedef typename def_type_helper<Expr, Auto>::type def_type; + + // create Defs map with only one entry: (ID -> def) + typedef typename + fusion::result_of::make_map<id_type, def_type>::type + defs_type; + + typedef subrule_group<defs_type> type; + }; + + template <typename Expr> + typename group_type_helper<Expr, false>::type + operator=(Expr const& expr) const + { + typedef group_type_helper<Expr, false> helper; + typedef typename helper::def_type def_type; + typedef typename helper::type result_type; + return result_type(fusion::make_map<id_type>( + def_type(compile<spirit::qi::domain>(expr), name_))); + } + + template <typename Expr> + friend typename group_type_helper<Expr, true>::type + operator%=(subrule const& sr, Expr const& expr) + { + typedef group_type_helper<Expr, true> helper; + typedef typename helper::def_type def_type; + typedef typename helper::type result_type; + return result_type(fusion::make_map<id_type>( + def_type(compile<spirit::qi::domain>(expr), sr.name_))); + } + + // non-const versions needed to suppress proto's %= kicking in + template <typename Expr> + friend typename group_type_helper<Expr, true>::type + operator%=(subrule const& sr, Expr& expr) + { + return operator%=( + sr + , static_cast<Expr const&>(expr)); + } + template <typename Expr> + friend typename group_type_helper<Expr, true>::type + operator%=(subrule& sr, Expr const& expr) + { + return operator%=( + static_cast<subrule const&>(sr) + , expr); + } + template <typename Expr> + friend typename group_type_helper<Expr, true>::type + operator%=(subrule& sr, Expr& expr) + { + return operator%=( + static_cast<subrule const&>(sr) + , static_cast<Expr const&>(expr)); + } + + std::string const& name() const + { + return name_; + } + + void name(std::string const& str) + { + name_ = str; + } + + template <typename Context, typename Iterator> + struct attribute + { + typedef attr_type type; + }; + + template <typename Iterator, typename Group + , typename Attributes, typename Locals + , typename Skipper, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , subrule_context<Group, Attributes, Locals>& context + , Skipper const& skipper, Attribute& attr) const + { + return context.group.template parse_subrule_id<ID_>( + first, last, context, skipper, attr); + } + + template <typename Iterator, typename Context + , typename Skipper, typename Attribute> + bool parse(Iterator& /*first*/, Iterator const& /*last*/ + , Context& /*context*/ + , Skipper const& /*skipper*/, Attribute& /*attr*/) const + { + // If you are seeing a compilation error here, you are trying + // to use a subrule as a parser outside of a subrule group. + BOOST_SPIRIT_ASSERT_MSG(false + , subrule_used_outside_subrule_group, (id_type)); + + return false; + } + + template <typename Iterator, typename Group + , typename Attributes, typename Locals + , typename Skipper, typename Attribute + , typename Params> + bool parse(Iterator& first, Iterator const& last + , subrule_context<Group, Attributes, Locals>& context + , Skipper const& skipper, Attribute& attr + , Params const& params) const + { + return context.group.template parse_subrule_id<ID_>( + first, last, context, skipper, attr, params); + } + + template <typename Iterator, typename Context + , typename Skipper, typename Attribute + , typename Params> + bool parse(Iterator& /*first*/, Iterator const& /*last*/ + , Context& /*context*/ + , Skipper const& /*skipper*/, Attribute& /*attr*/ + , Params const& /*params*/) const + { + // If you are seeing a compilation error here, you are trying + // to use a subrule as a parser outside of a subrule group. + BOOST_SPIRIT_ASSERT_MSG(false + , subrule_used_outside_subrule_group, (id_type)); + + return false; + } + + template <typename Context> + info what(Context& /*context*/) const + { + return info(name_); + } + + // bring in the operator() overloads + this_type const& get_parameterized_subject() const { return *this; } + typedef this_type parameterized_subject_type; + #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp> + + std::string name_; + }; +}}}} + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif diff --git a/boost/spirit/repository/home/qi/operator.hpp b/boost/spirit/repository/home/qi/operator.hpp new file mode 100644 index 0000000000..2c3606d007 --- /dev/null +++ b/boost/spirit/repository/home/qi/operator.hpp @@ -0,0 +1,17 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// 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_REPOSITORY_QI_OPERATOR_OCT_20_2010_1258PM) +#define SPIRIT_REPOSITORY_QI_OPERATOR_OCT_20_2010_1258PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/repository/home/qi/operator/keywords.hpp> +#endif + diff --git a/boost/spirit/repository/home/qi/operator/detail/keywords.hpp b/boost/spirit/repository/home/qi/operator/detail/keywords.hpp new file mode 100644 index 0000000000..81e17715df --- /dev/null +++ b/boost/spirit/repository/home/qi/operator/detail/keywords.hpp @@ -0,0 +1,117 @@ +/*============================================================================= + 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 { + + // 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 Elements, typename Iterator ,typename Context ,typename Skipper + ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass> + class parse_dispatcher + : public boost::static_visitor<bool> + { + typedef typename add_reference<Attribute>::type attr_reference; + + public: + parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last + , Context& context, Skipper const& skipper + , Flags &flags, Counters &counters, attr_reference 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; + skipper_keyword_marker<Skipper,NoCasePass> marked_skipper(skipper,flags[Index::value],counters[Index::value]); + + if(subject.parse(first,last,context,marked_skipper,unused)) + { + return true; + } + save = 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; + 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; + } + save = save; + return false; + } + + // Handle unused attributes + template <typename T> bool call(T &idx, mpl::false_) const{ + 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; + attr_reference attr; + }; + +}}}}} + +#endif diff --git a/boost/spirit/repository/home/qi/operator/keywords.hpp b/boost/spirit/repository/home/qi/operator/keywords.hpp new file mode 100644 index 0000000000..c32c55c7af --- /dev/null +++ b/boost/spirit/repository/home/qi/operator/keywords.hpp @@ -0,0 +1,640 @@ +/*============================================================================= + 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/at.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/spirit/home/qi/directive/hold.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> {}; + + template <typename Subject> + struct is_kwd_parser<spirit::qi::hold_directive<Subject> > : 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; + }; + 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< 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; + }; + 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<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; + } + + 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 + , 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 + diff --git a/boost/spirit/repository/home/qi/primitive.hpp b/boost/spirit/repository/home/qi/primitive.hpp new file mode 100644 index 0000000000..400e6d9626 --- /dev/null +++ b/boost/spirit/repository/home/qi/primitive.hpp @@ -0,0 +1,19 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// Copyright (c) 2001-2011 Joel de Guzman +// +// 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_REPOSITORY_QI_PRIMITIVE_APR_28_2009_1258PM) +#define SPIRIT_REPOSITORY_QI_PRIMITIVE_APR_28_2009_1258PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/repository/home/qi/primitive/advance.hpp> +#include <boost/spirit/repository/home/qi/primitive/flush_multi_pass.hpp> +#include <boost/spirit/repository/home/qi/primitive/iter_pos.hpp> + +#endif + diff --git a/boost/spirit/repository/home/qi/primitive/advance.hpp b/boost/spirit/repository/home/qi/primitive/advance.hpp new file mode 100644 index 0000000000..11a74bbb13 --- /dev/null +++ b/boost/spirit/repository/home/qi/primitive/advance.hpp @@ -0,0 +1,130 @@ +// Copyright (c) 2011 Aaron Graham +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_SPIRIT_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM) +#define BOOST_SPIRIT_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM + +#include <boost/spirit/include/qi_parse.hpp> + +/////////////////////////////////////////////////////////////////////////////// +// definition the place holder +namespace boost { namespace spirit { namespace repository { namespace qi +{ + BOOST_SPIRIT_TERMINAL_EX(advance); +}}}} + +/////////////////////////////////////////////////////////////////////////////// +// implementation the enabler +namespace boost { namespace spirit +{ + template <typename A0> + struct use_terminal<qi::domain + , terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> > > + : mpl::or_<is_integral<A0>, is_enum<A0> > + {}; + + template <> + struct use_lazy_terminal<qi::domain, repository::qi::tag::advance, 1> + : mpl::true_ + {}; +}} + +/////////////////////////////////////////////////////////////////////////////// +// implementation of the parser +namespace boost { namespace spirit { namespace repository { namespace qi +{ + template <typename Int> + struct advance_parser + : boost::spirit::qi::primitive_parser< advance_parser<Int> > + { + // Define the attribute type exposed by this parser component + template <typename Context, typename Iterator> + struct attribute + { + typedef boost::spirit::unused_type type; + }; + + advance_parser(Int dist) + : dist(dist) + {} + + // This function is called during the actual parsing process + template <typename Iterator, typename Context + , typename Skipper, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context&, Skipper&, Attribute&) const + { + // This series of checks is designed to fail parsing on negative + // values, without generating a "expression always evaluates true" + // warning on unsigned types. + if (dist == Int(0)) return true; + if (dist < Int(1)) return false; + + typedef typename std::iterator_traits<Iterator>::iterator_category + iterator_category; + return advance(first, last, iterator_category()); + } + + // This function is called during error handling to create + // a human readable string for the error context. + template <typename Context> + boost::spirit::info what(Context&) const + { + return boost::spirit::info("advance"); + } + + private: + // this is the general implementation used by most iterator categories + template <typename Iterator, typename IteratorCategory> + bool advance(Iterator& first, Iterator const& last + , IteratorCategory) const + { + Int n = dist; + Iterator i = first; + while (n) + { + if (i == last) return false; + ++i; + --n; + } + first = i; + return true; + } + + // this is a specialization for random access iterators + template <typename Iterator> + bool advance(Iterator& first, Iterator const& last + , std::random_access_iterator_tag) const + { + Iterator const it = first + dist; + if (it > last) return false; + first = it; + return true; + } + + Int const dist; + }; +}}}} + +/////////////////////////////////////////////////////////////////////////////// +// instantiation of the parser +namespace boost { namespace spirit { namespace qi +{ + template <typename Modifiers, typename A0> + struct make_primitive< + terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> > + , Modifiers> + { + typedef repository::qi::advance_parser<A0> result_type; + + template <typename Terminal> + result_type operator()(Terminal const& term, unused_type) const + { + return result_type(fusion::at_c<0>(term.args)); + } + }; +}}} + +#endif diff --git a/boost/spirit/repository/home/qi/primitive/flush_multi_pass.hpp b/boost/spirit/repository/home/qi/primitive/flush_multi_pass.hpp new file mode 100644 index 0000000000..cd4ab0c0ca --- /dev/null +++ b/boost/spirit/repository/home/qi/primitive/flush_multi_pass.hpp @@ -0,0 +1,92 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_SPIRIT_REPOSITORY_QI_FLUSH_MULTI_PASS_JUL_10_2009_0535PM) +#define BOOST_SPIRIT_REPOSITORY_QI_FLUSH_MULTI_PASS_JUL_10_2009_0535PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/qi/domain.hpp> +#include <boost/spirit/home/qi/meta_compiler.hpp> +#include <boost/spirit/home/support/common_terminals.hpp> +#include <boost/spirit/home/support/info.hpp> +#include <boost/spirit/home/support/unused.hpp> +#include <boost/spirit/home/support/attributes.hpp> +#include <boost/spirit/home/support/multi_pass.hpp> + +#include <boost/spirit/repository/home/support/flush_multi_pass.hpp> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit +{ + /////////////////////////////////////////////////////////////////////////// + // Enablers + /////////////////////////////////////////////////////////////////////////// + + // enables flush_multi_pass + template <> + struct use_terminal<qi::domain, repository::tag::flush_multi_pass> + : mpl::true_ {}; + +}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace repository { namespace qi +{ + using repository::flush_multi_pass_type; + using repository::flush_multi_pass; + + /////////////////////////////////////////////////////////////////////////// + // for a flush_multi_pass_parser generated parser + struct flush_multi_pass_parser + : spirit::qi::primitive_parser<flush_multi_pass_parser> + { + template <typename Context, typename Unused> + struct attribute + { + typedef unused_type type; + }; + + template <typename Iterator, typename Context + , typename Skipper, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context& context, Skipper const& skipper + , Attribute& attr) const + { + spirit::traits::clear_queue(first, traits::clear_mode::clear_always); + return true; + } + + template <typename Context> + info what(Context const& ctx) const + { + return info("flush_multi_pass"); + } + }; + +}}}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace qi +{ + /////////////////////////////////////////////////////////////////////////// + // Parser generators: make_xxx function (objects) + /////////////////////////////////////////////////////////////////////////// + template <typename Modifiers> + struct make_primitive<repository::tag::flush_multi_pass, Modifiers> + { + typedef repository::qi::flush_multi_pass_parser result_type; + result_type operator()(unused_type, unused_type) const + { + return result_type(); + } + }; + +}}} + +#endif + diff --git a/boost/spirit/repository/home/qi/primitive/iter_pos.hpp b/boost/spirit/repository/home/qi/primitive/iter_pos.hpp new file mode 100644 index 0000000000..6925ac2241 --- /dev/null +++ b/boost/spirit/repository/home/qi/primitive/iter_pos.hpp @@ -0,0 +1,83 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_SPIRIT_REPOSITORY_QI_ITER_POS_NOV_20_2009_1245PM) +#define BOOST_SPIRIT_REPOSITORY_QI_ITER_POS_NOV_20_2009_1245PM + +#include <boost/spirit/include/qi_parse.hpp> + +/////////////////////////////////////////////////////////////////////////////// +// definition the place holder +namespace boost { namespace spirit { namespace repository { namespace qi +{ + BOOST_SPIRIT_TERMINAL(iter_pos); +}}}} + +/////////////////////////////////////////////////////////////////////////////// +// implementation the enabler +namespace boost { namespace spirit +{ + // We want custom_parser::iter_pos to be usable as a terminal only, + // and only for parser expressions (qi::domain). + template <> + struct use_terminal<qi::domain, repository::qi::tag::iter_pos> + : mpl::true_ + {}; +}} + +/////////////////////////////////////////////////////////////////////////////// +// implementation of the parser +namespace boost { namespace spirit { namespace repository { namespace qi +{ + struct iter_pos_parser + : boost::spirit::qi::primitive_parser<iter_pos_parser> + { + // Define the attribute type exposed by this parser component + template <typename Context, typename Iterator> + struct attribute + { + typedef Iterator type; + }; + + // This function is called during the actual parsing process + template <typename Iterator, typename Context + , typename Skipper, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context&, Skipper const& skipper, Attribute& attr) const + { + boost::spirit::qi::skip_over(first, last, skipper); + boost::spirit::traits::assign_to(first, attr); + return true; + } + + // This function is called during error handling to create + // a human readable string for the error context. + template <typename Context> + boost::spirit::info what(Context&) const + { + return boost::spirit::info("iter_pos"); + } + }; +}}}} + +/////////////////////////////////////////////////////////////////////////////// +// instantiation of the parser +namespace boost { namespace spirit { namespace qi +{ + // This is the factory function object invoked in order to create + // an instance of our iter_pos_parser. + template <typename Modifiers> + struct make_primitive<repository::qi::tag::iter_pos, Modifiers> + { + typedef repository::qi::iter_pos_parser result_type; + + result_type operator()(unused_type, unused_type) const + { + return result_type(); + } + }; +}}} + +#endif |