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