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
30namespace 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
44namespace 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
68 alternative(Elements const& elements_)
69 : elements(elements_) {}
70
71 template <typename Iterator, typename Context
72 , typename Skipper, typename Attribute>
73 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>
85 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
105namespace 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

source code of boost/libs/spirit/include/boost/spirit/home/qi/operator/alternative.hpp