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_OPTIONAL_HPP 9 #define BOOST_SPIRIT_QI_OPERATOR_OPTIONAL_HPP 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 <boost/proto/operators.hpp> 26 #include <boost/proto/tags.hpp> 27 #include <vector> 28 29 namespace boost { namespace spirit 30 { 31 /////////////////////////////////////////////////////////////////////////// 32 // Enablers 33 /////////////////////////////////////////////////////////////////////////// 34 template <> 35 struct use_operator<qi::domain, proto::tag::negate> // enables -p 36 : mpl::true_ {}; 37 }} 38 39 namespace boost { namespace spirit { namespace qi 40 { 41 template <typename Subject> 42 struct optional : unary_parser<optional<Subject> > 43 { 44 typedef Subject subject_type; 45 46 template <typename Context, typename Iterator> 47 struct attribute 48 { 49 // Build a boost::optional from the subject's attribute. Note 50 // that boost::optional may return unused_type if the 51 // subject's attribute is an unused_type. 52 typedef typename 53 traits::build_optional< 54 typename traits:: 55 attribute_of<Subject, Context, Iterator>::type 56 >::type 57 type; 58 }; 59 optionalboost::spirit::qi::optional60 optional(Subject const& subject_) 61 : subject(subject_) {} 62 63 template <typename Iterator, typename Context 64 , typename Skipper, typename Attribute> parse_implboost::spirit::qi::optional65 bool parse_impl(Iterator& first, Iterator const& last 66 , Context& context, Skipper const& skipper 67 , Attribute& attr_, mpl::false_) const 68 { 69 // create a local value if Attribute is not unused_type 70 typename spirit::result_of::optional_value<Attribute>::type val = 71 typename spirit::result_of::optional_value<Attribute>::type(); 72 73 if (subject.parse(first, last, context, skipper, val)) 74 { 75 // assign the parsed value into our attribute 76 spirit::traits::assign_to(val, attr_); 77 } 78 return true; 79 } 80 81 template <typename Iterator, typename Context 82 , typename Skipper, typename Attribute> parse_implboost::spirit::qi::optional83 bool parse_impl(Iterator& first, Iterator const& last 84 , Context& context, Skipper const& skipper 85 , Attribute& attr_, mpl::true_) const 86 { 87 subject.parse(first, last, context, skipper, attr_); 88 return true; 89 } 90 91 template <typename Iterator, typename Context 92 , typename Skipper, typename Attribute> parseboost::spirit::qi::optional93 bool parse(Iterator& first, Iterator const& last 94 , Context& context, Skipper const& skipper 95 , Attribute& attr_) const 96 { 97 typedef typename spirit::result_of::optional_value<Attribute>::type 98 attribute_type; 99 100 return parse_impl(first, last, context, skipper, attr_ 101 , traits::is_container<attribute_type>()); 102 } 103 104 template <typename Context> whatboost::spirit::qi::optional105 info what(Context& context) const 106 { 107 return info("optional", subject.what(context)); 108 } 109 110 Subject subject; 111 }; 112 113 /////////////////////////////////////////////////////////////////////////// 114 // Parser generators: make_xxx function (objects) 115 /////////////////////////////////////////////////////////////////////////// 116 template <typename Elements, typename Modifiers> 117 struct make_composite<proto::tag::negate, Elements, Modifiers> 118 : make_unary_composite<Elements, optional> 119 {}; 120 }}} 121 122 namespace boost { namespace spirit { namespace traits 123 { 124 /////////////////////////////////////////////////////////////////////////// 125 template <typename Subject> 126 struct has_semantic_action<qi::optional<Subject> > 127 : unary_has_semantic_action<Subject> {}; 128 129 /////////////////////////////////////////////////////////////////////////// 130 template <typename Subject, typename Attribute, typename Context 131 , typename Iterator> 132 struct handles_container<qi::optional<Subject>, Attribute 133 , Context, Iterator> 134 : mpl::true_ {}; 135 }}} 136 137 #endif 138