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_LIST_HPP 9 #define BOOST_SPIRIT_QI_OPERATOR_LIST_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 #include <vector> 27 28 namespace boost { namespace spirit 29 { 30 /////////////////////////////////////////////////////////////////////////// 31 // Enablers 32 /////////////////////////////////////////////////////////////////////////// 33 template <> 34 struct use_operator<qi::domain, proto::tag::modulus> // enables p % d 35 : mpl::true_ {}; 36 }} 37 38 namespace boost { namespace spirit { namespace qi 39 { 40 template <typename Left, typename Right> 41 struct list : binary_parser<list<Left, Right> > 42 { 43 typedef Left left_type; 44 typedef Right right_type; 45 46 template <typename Context, typename Iterator> 47 struct attribute 48 { 49 // Build a std::vector from the LHS's attribute. Note 50 // that build_std_vector may return unused_type if the 51 // subject's attribute is an unused_type. 52 typedef typename 53 traits::build_std_vector< 54 typename traits:: 55 attribute_of<Left, Context, Iterator>::type 56 >::type 57 type; 58 }; 59 listboost::spirit::qi::list60 list(Left const& left_, Right const& right_) 61 : left(left_), right(right_) {} 62 63 template <typename F> parse_containerboost::spirit::qi::list64 bool parse_container(F f) const 65 { 66 // in order to succeed we need to match at least one element 67 if (f (left)) 68 return false; 69 70 typename F::iterator_type save = f.f.first; 71 while (right.parse(f.f.first, f.f.last, f.f.context, f.f.skipper, unused) 72 && !f (left)) 73 { 74 save = f.f.first; 75 } 76 77 f.f.first = save; 78 return true; 79 } 80 81 template <typename Iterator, typename Context 82 , typename Skipper, typename Attribute> parseboost::spirit::qi::list83 bool parse(Iterator& first, Iterator const& last 84 , Context& context, Skipper const& skipper 85 , Attribute& attr_) const 86 { 87 typedef detail::fail_function<Iterator, Context, Skipper> 88 fail_function; 89 90 // ensure the attribute is actually a container type 91 traits::make_container(attr_); 92 93 Iterator iter = first; 94 fail_function f(iter, last, context, skipper); 95 if (!parse_container(detail::make_pass_container(f, attr_))) 96 return false; 97 98 first = f.first; 99 return true; 100 } 101 102 template <typename Context> whatboost::spirit::qi::list103 info what(Context& context) const 104 { 105 return info("list", 106 std::make_pair(left.what(context), right.what(context))); 107 } 108 109 Left left; 110 Right right; 111 }; 112 113 /////////////////////////////////////////////////////////////////////////// 114 // Parser generators: make_xxx function (objects) 115 /////////////////////////////////////////////////////////////////////////// 116 template <typename Elements, typename Modifiers> 117 struct make_composite<proto::tag::modulus, Elements, Modifiers> 118 : make_binary_composite<Elements, list> 119 {}; 120 }}} 121 122 namespace boost { namespace spirit { namespace traits 123 { 124 /////////////////////////////////////////////////////////////////////////// 125 template <typename Left, typename Right> 126 struct has_semantic_action<qi::list<Left, Right> > 127 : binary_has_semantic_action<Left, Right> {}; 128 129 /////////////////////////////////////////////////////////////////////////// 130 template <typename Left, typename Right, typename Attribute 131 , typename Context, typename Iterator> 132 struct handles_container<qi::list<Left, Right>, Attribute, Context 133 , Iterator> 134 : mpl::true_ {}; 135 }}} 136 137 #endif 138