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_PLUS_HPP 9 #define BOOST_SPIRIT_QI_OPERATOR_PLUS_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 template <> 33 struct use_operator<qi::domain, proto::tag::unary_plus> // enables +p 34 : mpl::true_ {}; 35 }} 36 37 namespace boost { namespace spirit { namespace qi 38 { 39 template <typename Subject> 40 struct plus : unary_parser<plus<Subject> > 41 { 42 typedef Subject subject_type; 43 44 template <typename Context, typename Iterator> 45 struct attribute 46 { 47 // Build a std::vector from the subject's attribute. Note 48 // that build_std_vector may return unused_type if the 49 // subject's attribute is an unused_type. 50 typedef typename 51 traits::build_std_vector< 52 typename traits::attribute_of< 53 Subject, Context, Iterator>::type 54 >::type 55 type; 56 }; 57 plusboost::spirit::qi::plus58 plus(Subject const& subject_) 59 : subject(subject_) {} 60 61 template <typename F> parse_containerboost::spirit::qi::plus62 bool parse_container(F f) const 63 { 64 // in order to succeed we need to match at least one element 65 if (f (subject)) 66 return false; 67 68 while (!f (subject)) 69 ; 70 return true; 71 } 72 73 template <typename Iterator, typename Context 74 , typename Skipper, typename Attribute> parseboost::spirit::qi::plus75 bool parse(Iterator& first, Iterator const& last 76 , Context& context, Skipper const& skipper 77 , Attribute& attr_) const 78 { 79 typedef detail::fail_function<Iterator, Context, Skipper> 80 fail_function; 81 82 // ensure the attribute is actually a container type 83 traits::make_container(attr_); 84 85 Iterator iter = first; 86 fail_function f(iter, last, context, skipper); 87 if (!parse_container(detail::make_pass_container(f, attr_))) 88 return false; 89 90 first = f.first; 91 return true; 92 } 93 94 template <typename Context> whatboost::spirit::qi::plus95 info what(Context& context) const 96 { 97 return info("plus", subject.what(context)); 98 } 99 100 Subject subject; 101 }; 102 103 /////////////////////////////////////////////////////////////////////////// 104 // Parser generators: make_xxx function (objects) 105 /////////////////////////////////////////////////////////////////////////// 106 template <typename Elements, typename Modifiers> 107 struct make_composite<proto::tag::unary_plus, Elements, Modifiers> 108 : make_unary_composite<Elements, plus> 109 {}; 110 }}} 111 112 namespace boost { namespace spirit { namespace traits 113 { 114 /////////////////////////////////////////////////////////////////////////// 115 template <typename Subject> 116 struct has_semantic_action<qi::plus<Subject> > 117 : unary_has_semantic_action<Subject> {}; 118 119 /////////////////////////////////////////////////////////////////////////// 120 template <typename Subject, typename Attribute, typename Context 121 , typename Iterator> 122 struct handles_container<qi::plus<Subject>, Attribute, Context 123 , Iterator> 124 : mpl::true_ {}; 125 }}} 126 127 #endif 128