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