1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 Copyright (c) 2001-2011 Hartmut Kaiser 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 =============================================================================*/ 8 #ifndef BOOST_SPIRIT_QI_OPERATOR_KLEENE_HPP 9 #define BOOST_SPIRIT_QI_OPERATOR_KLEENE_HPP 10 11 #if defined(_MSC_VER) 12 #pragma once 13 #endif 14 15 #include <boost/spirit/home/qi/meta_compiler.hpp> 16 #include <boost/spirit/home/qi/parser.hpp> 17 #include <boost/spirit/home/support/container.hpp> 18 #include <boost/spirit/home/qi/detail/attributes.hpp> 19 #include <boost/spirit/home/qi/detail/fail_function.hpp> 20 #include <boost/spirit/home/qi/detail/pass_container.hpp> 21 #include <boost/spirit/home/support/has_semantic_action.hpp> 22 #include <boost/spirit/home/support/handles_container.hpp> 23 #include <boost/spirit/home/support/info.hpp> 24 #include <boost/proto/operators.hpp> 25 #include <boost/proto/tags.hpp> 26 27 namespace boost { namespace spirit 28 { 29 /////////////////////////////////////////////////////////////////////////// 30 // Enablers 31 /////////////////////////////////////////////////////////////////////////// 32 //[composite_parsers_kleene_enable_ 33 template <> 34 struct use_operator<qi::domain, proto::tag::dereference> // enables *p 35 : mpl::true_ {}; 36 //] 37 }} 38 39 namespace boost { namespace spirit { namespace qi 40 { 41 //[composite_parsers_kleene 42 template <typename Subject> 43 struct kleene : unary_parser<kleene<Subject> > 44 { 45 typedef Subject subject_type; 46 47 template <typename Context, typename Iterator> 48 struct attribute 49 { 50 // Build a std::vector from the subject's attribute. Note 51 // that build_std_vector may return unused_type if the 52 // subject's attribute is an unused_type. 53 typedef typename 54 traits::build_std_vector< 55 typename traits:: 56 attribute_of<Subject, Context, Iterator>::type 57 >::type 58 type; 59 }; 60 kleeneboost::spirit::qi::kleene61 kleene(Subject const& subject_) 62 : subject(subject_) {} 63 64 template <typename F> parse_containerboost::spirit::qi::kleene65 bool parse_container(F f) const 66 { 67 while (!f (subject)) 68 ; 69 return true; 70 } 71 72 template <typename Iterator, typename Context 73 , typename Skipper, typename Attribute> parseboost::spirit::qi::kleene74 bool parse(Iterator& first, Iterator const& last 75 , Context& context, Skipper const& skipper 76 , Attribute& attr_) const 77 { 78 // ensure the attribute is actually a container type 79 traits::make_container(attr_); 80 81 typedef detail::fail_function<Iterator, Context, Skipper> 82 fail_function; 83 84 Iterator iter = first; 85 fail_function f(iter, last, context, skipper); 86 parse_container(detail::make_pass_container(f, attr_)); 87 88 first = f.first; 89 return true; 90 } 91 92 template <typename Context> whatboost::spirit::qi::kleene93 info what(Context& context) const 94 { 95 return info("kleene", subject.what(context)); 96 } 97 98 Subject subject; 99 }; 100 //] 101 102 /////////////////////////////////////////////////////////////////////////// 103 // Parser generators: make_xxx function (objects) 104 /////////////////////////////////////////////////////////////////////////// 105 //[composite_parsers_kleene_generator 106 template <typename Elements, typename Modifiers> 107 struct make_composite<proto::tag::dereference, Elements, Modifiers> 108 : make_unary_composite<Elements, kleene> 109 {}; 110 //] 111 112 // /////////////////////////////////////////////////////////////////////////// 113 // // Define what attributes are compatible with a kleene 114 // template <typename Attribute, typename Subject, typename Context, typename Iterator> 115 // struct is_attribute_compatible<Attribute, kleene<Subject>, Context, Iterator> 116 // : traits::is_container_compatible<qi::domain, Attribute 117 // , kleene<Subject>, Context, Iterator> 118 // {}; 119 }}} 120 121 namespace boost { namespace spirit { namespace traits 122 { 123 /////////////////////////////////////////////////////////////////////////// 124 template <typename Subject> 125 struct has_semantic_action<qi::kleene<Subject> > 126 : unary_has_semantic_action<Subject> {}; 127 128 /////////////////////////////////////////////////////////////////////////// 129 template <typename Subject, typename Attribute, typename Context 130 , typename Iterator> 131 struct handles_container<qi::kleene<Subject>, Attribute 132 , Context, Iterator> 133 : mpl::true_ {}; 134 }}} 135 136 #endif 137