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