/*============================================================================= 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 #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace spirit { /////////////////////////////////////////////////////////////////////////// // Enablers /////////////////////////////////////////////////////////////////////////// template < typename T> struct use_directive > > : traits::is_string {}; template < typename T> struct use_directive > > : traits::is_string {}; template < typename T1, typename T2> struct use_directive > > : traits::is_string {}; template < typename T1, typename T2> struct use_directive > > : traits::is_string {}; template < typename T1, typename T2> struct use_directive > > : traits::is_string {}; template < typename T1, typename T2> struct use_directive > > : traits::is_string {}; template < typename T1, typename T2> struct use_directive > > : traits::is_string {}; template < typename T1, typename T2> struct use_directive > > : traits::is_string {}; /* 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 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 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 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 && 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 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 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 struct kwd_parser : spirit::qi::unary_parser > { struct kwd_parser_id; typedef Subject subject_type; typedef NoCase no_case_keyword; typedef typename remove_const::type>::type char_type; typedef std::basic_string keyword_type; template 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::type keyword , LoopIter const& iter) : subject(subject), iter(iter), keyword(keyword) {} // Call the subject parser on a non container attribute template 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 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::type val = typename traits::container_value::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 bool parse(Iterator& first, Iterator const& last , Context& context, skipper_keyword_marker const& skipper , Attribute &attr) const { typedef typename traits::attribute_of< Subject, Context, Iterator>::type subject_attribute; typedef typename mpl::and_< traits::is_container , 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 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 , 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 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 keyword; private: // silence MSVC warning C4512: assignment operator could not be generated kwd_parser& operator= (kwd_parser const&); template static spirit::qi::detail::fail_function fail_function( Iterator& first, Iterator const& last , Context& context, Skipper const& skipper) { return spirit::qi::detail::fail_function (first, last, context, skipper); } }; }}}} /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { namespace qi { /////////////////////////////////////////////////////////////////////////// // Parser generators: make_xxx function (objects) /////////////////////////////////////////////////////////////////////////// // Directive kwd(key)[p] template struct make_directive< terminal_ex >, Subject, Modifiers> { typedef typename add_const::type const_keyword; typedef repository::qi::kwd_pass_iterator iterator_type; typedef has_modifier > no_case; typedef repository::qi::kwd_parser result_type; template 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 struct make_directive< terminal_ex >, Subject, Modifiers> { typedef typename add_const::type const_keyword; typedef repository::qi::kwd_pass_iterator iterator_type; typedef repository::qi::kwd_parser result_type; template result_type operator()( Terminal const& term, Subject const& subject, unused_type) const { /* typename spirit::detail::get_encoding::type encoding;*/ return result_type(subject ,fusion::at_c<0>(term.args) ,iterator_type() ); } }; // Directive kwd(key,exact)[p] template struct make_directive< terminal_ex >, Subject, Modifiers> { typedef typename add_const::type const_keyword; typedef repository::qi::kwd_exact_iterator iterator_type; typedef has_modifier > no_case; typedef repository::qi::kwd_parser result_type; template 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 struct make_directive< terminal_ex >, Subject, Modifiers> { typedef typename add_const::type const_keyword; typedef repository::qi::kwd_exact_iterator iterator_type; typedef repository::qi::kwd_parser result_type; template 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 struct make_directive< terminal_ex >, Subject, Modifiers> { typedef typename add_const::type const_keyword; typedef repository::qi::kwd_finite_iterator iterator_type; typedef has_modifier > no_case; typedef repository::qi::kwd_parser result_type; template 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 struct make_directive< terminal_ex >, Subject, Modifiers> { typedef typename add_const::type const_keyword; typedef repository::qi::kwd_finite_iterator iterator_type; typedef repository::qi::kwd_parser result_type; template 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 struct make_directive< terminal_ex >, Subject, Modifiers> { typedef typename add_const::type const_keyword; typedef repository::qi::kwd_infinite_iterator iterator_type; typedef has_modifier > no_case; typedef repository::qi::kwd_parser result_type; template 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 struct make_directive< terminal_ex >, Subject, Modifiers> { typedef typename add_const::type const_keyword; typedef repository::qi::kwd_infinite_iterator iterator_type; typedef repository::qi::kwd_parser result_type; template result_type operator()( Terminal const& term, Subject const& subject, unused_type) const { typename spirit::detail::get_encoding::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 struct has_semantic_action< repository::qi::kwd_parser< Subject, KeywordType, LoopIter, NoCase > > : unary_has_semantic_action {}; }}} #endif