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_ALTERNATIVE_HPP 9 #define BOOST_SPIRIT_QI_OPERATOR_ALTERNATIVE_HPP 10 11 #if defined(_MSC_VER) 12 #pragma once 13 #endif 14 15 #include <boost/spirit/home/qi/detail/alternative_function.hpp> 16 #include <boost/spirit/home/qi/meta_compiler.hpp> 17 #include <boost/spirit/home/qi/parser.hpp> 18 #include <boost/spirit/home/qi/detail/attributes.hpp> 19 #include <boost/spirit/home/support/has_semantic_action.hpp> 20 #include <boost/spirit/home/support/handles_container.hpp> 21 #include <boost/spirit/home/support/detail/what_function.hpp> 22 #include <boost/spirit/home/support/unused.hpp> 23 #include <boost/spirit/home/support/info.hpp> 24 #include <boost/fusion/include/any.hpp> 25 #include <boost/fusion/include/mpl.hpp> 26 #include <boost/fusion/include/for_each.hpp> 27 #include <boost/proto/operators.hpp> 28 #include <boost/proto/tags.hpp> 29 30 namespace boost { namespace spirit 31 { 32 /////////////////////////////////////////////////////////////////////////// 33 // Enablers 34 /////////////////////////////////////////////////////////////////////////// 35 template <> 36 struct use_operator<qi::domain, proto::tag::bitwise_or> // enables | 37 : mpl::true_ {}; 38 39 template <> 40 struct flatten_tree<qi::domain, proto::tag::bitwise_or> // flattens | 41 : mpl::true_ {}; 42 }} 43 44 namespace boost { namespace spirit { namespace qi 45 { 46 template <typename Elements> 47 struct alternative : nary_parser<alternative<Elements> > 48 { 49 template <typename Context, typename Iterator> 50 struct attribute 51 { 52 // Put all the element attributes in a tuple 53 typedef typename traits::build_attribute_sequence< 54 Elements, Context, traits::alternative_attribute_transform 55 , Iterator, qi::domain 56 >::type all_attributes; 57 58 // Ok, now make a variant over the attribute sequence. Note that 59 // build_variant makes sure that 1) all attributes in the variant 60 // are unique 2) puts the unused attribute, if there is any, to 61 // the front and 3) collapses single element variants, variant<T> 62 // to T. 63 typedef typename 64 traits::build_variant<all_attributes>::type 65 type; 66 }; 67 alternativeboost::spirit::qi::alternative68 alternative(Elements const& elements_) 69 : elements(elements_) {} 70 71 template <typename Iterator, typename Context 72 , typename Skipper, typename Attribute> parseboost::spirit::qi::alternative73 bool parse(Iterator& first, Iterator const& last 74 , Context& context, Skipper const& skipper 75 , Attribute& attr_) const 76 { 77 detail::alternative_function<Iterator, Context, Skipper, Attribute> 78 f(first, last, context, skipper, attr_); 79 80 // return true if *any* of the parsers succeed 81 return fusion::any(elements, f); 82 } 83 84 template <typename Context> whatboost::spirit::qi::alternative85 info what(Context& context) const 86 { 87 info result("alternative"); 88 fusion::for_each(elements, 89 spirit::detail::what_function<Context>(result, context)); 90 return result; 91 } 92 93 Elements elements; 94 }; 95 96 /////////////////////////////////////////////////////////////////////////// 97 // Parser generators: make_xxx function (objects) 98 /////////////////////////////////////////////////////////////////////////// 99 template <typename Elements, typename Modifiers> 100 struct make_composite<proto::tag::bitwise_or, Elements, Modifiers> 101 : make_nary_composite<Elements, alternative> 102 {}; 103 }}} 104 105 namespace boost { namespace spirit { namespace traits 106 { 107 /////////////////////////////////////////////////////////////////////////// 108 template <typename Elements> 109 struct has_semantic_action<qi::alternative<Elements> > 110 : nary_has_semantic_action<Elements> {}; 111 112 /////////////////////////////////////////////////////////////////////////// 113 template <typename Elements, typename Attribute, typename Context 114 , typename Iterator> 115 struct handles_container<qi::alternative<Elements>, Attribute, Context 116 , Iterator> 117 : nary_handles_container<Elements, Attribute, Context, Iterator> {}; 118 }}} 119 120 #endif 121