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_OPTIONAL_MARCH_23_2007_1117PM) 9 #define SPIRIT_OPTIONAL_MARCH_23_2007_1117PM 10 11 #if defined(_MSC_VER) 12 #pragma once 13 #endif 14 15 #include <boost/spirit/home/support/unused.hpp> 16 #include <boost/spirit/home/qi/detail/attributes.hpp> 17 #include <boost/spirit/home/support/has_semantic_action.hpp> 18 #include <boost/spirit/home/support/handles_container.hpp> 19 #include <boost/spirit/home/support/info.hpp> 20 #include <boost/spirit/home/support/container.hpp> 21 #include <boost/spirit/home/qi/parser.hpp> 22 #include <boost/spirit/home/qi/meta_compiler.hpp> 23 #include <boost/spirit/home/qi/detail/assign_to.hpp> 24 #include <boost/optional.hpp> 25 #include <vector> 26 27 namespace boost { namespace spirit 28 { 29 /////////////////////////////////////////////////////////////////////////// 30 // Enablers 31 /////////////////////////////////////////////////////////////////////////// 32 template <> 33 struct use_operator<qi::domain, proto::tag::negate> // enables -p 34 : mpl::true_ {}; 35 }} 36 37 namespace boost { namespace spirit { namespace qi 38 { 39 template <typename Subject> 40 struct optional : unary_parser<optional<Subject> > 41 { 42 typedef Subject subject_type; 43 44 template <typename Context, typename Iterator> 45 struct attribute 46 { 47 // Build a boost::optional from the subject's attribute. Note 48 // that boost::optional may return unused_type if the 49 // subject's attribute is an unused_type. 50 typedef typename 51 traits::build_optional< 52 typename traits:: 53 attribute_of<Subject, Context, Iterator>::type 54 >::type 55 type; 56 }; 57 optionalboost::spirit::qi::optional58 optional(Subject const& subject_) 59 : subject(subject_) {} 60 61 template <typename Iterator, typename Context 62 , typename Skipper, typename Attribute> parse_implboost::spirit::qi::optional63 bool parse_impl(Iterator& first, Iterator const& last 64 , Context& context, Skipper const& skipper 65 , Attribute& attr_, mpl::false_) const 66 { 67 // create a local value if Attribute is not unused_type 68 typename spirit::result_of::optional_value<Attribute>::type val = 69 typename spirit::result_of::optional_value<Attribute>::type(); 70 71 if (subject.parse(first, last, context, skipper, val)) 72 { 73 // assign the parsed value into our attribute 74 spirit::traits::assign_to(val, attr_); 75 } 76 return true; 77 } 78 79 template <typename Iterator, typename Context 80 , typename Skipper, typename Attribute> parse_implboost::spirit::qi::optional81 bool parse_impl(Iterator& first, Iterator const& last 82 , Context& context, Skipper const& skipper 83 , Attribute& attr_, mpl::true_) const 84 { 85 subject.parse(first, last, context, skipper, attr_); 86 return true; 87 } 88 89 template <typename Iterator, typename Context 90 , typename Skipper, typename Attribute> parseboost::spirit::qi::optional91 bool parse(Iterator& first, Iterator const& last 92 , Context& context, Skipper const& skipper 93 , Attribute& attr_) const 94 { 95 typedef typename spirit::result_of::optional_value<Attribute>::type 96 attribute_type; 97 98 return parse_impl(first, last, context, skipper, attr_ 99 , traits::is_container<attribute_type>()); 100 } 101 102 template <typename Context> whatboost::spirit::qi::optional103 info what(Context& context) const 104 { 105 return info("optional", subject.what(context)); 106 } 107 108 Subject subject; 109 }; 110 111 /////////////////////////////////////////////////////////////////////////// 112 // Parser generators: make_xxx function (objects) 113 /////////////////////////////////////////////////////////////////////////// 114 template <typename Elements, typename Modifiers> 115 struct make_composite<proto::tag::negate, Elements, Modifiers> 116 : make_unary_composite<Elements, optional> 117 {}; 118 }}} 119 120 namespace boost { namespace spirit { namespace traits 121 { 122 /////////////////////////////////////////////////////////////////////////// 123 template <typename Subject> 124 struct has_semantic_action<qi::optional<Subject> > 125 : unary_has_semantic_action<Subject> {}; 126 127 /////////////////////////////////////////////////////////////////////////// 128 template <typename Subject, typename Attribute, typename Context 129 , typename Iterator> 130 struct handles_container<qi::optional<Subject>, Attribute 131 , Context, Iterator> 132 : mpl::true_ {}; 133 }}} 134 135 #endif 136