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