1 ///////////////////////////////////////////////////////////////////////////////
2 // as_alternate.hpp
3 //
4 //  Copyright 2008 Eric Niebler. Distributed under the Boost
5 //  Software License, Version 1.0. (See accompanying file
6 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #ifndef BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_ALTERNATE_HPP_EAN_04_01_2007
9 #define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_ALTERNATE_HPP_EAN_04_01_2007
10 
11 // MS compatible compilers support #pragma once
12 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
13 # pragma once
14 #endif
15 
16 #include <boost/config.hpp>
17 #include <boost/mpl/assert.hpp>
18 #include <boost/type_traits/is_same.hpp>
19 #include <boost/xpressive/proto/proto.hpp>
20 #include <boost/xpressive/detail/detail_fwd.hpp>
21 #include <boost/xpressive/detail/static/static.hpp>
22 #include <boost/xpressive/detail/core/matcher/alternate_matcher.hpp>
23 #include <boost/xpressive/detail/utility/cons.hpp>
24 
25 namespace boost { namespace xpressive
26 {
27     namespace detail
28     {
29         ///////////////////////////////////////////////////////////////////////////////
30         // alternates_list
31         //   a fusion-compatible sequence of alternate expressions, that also keeps
32         //   track of the list's width and purity.
33         template<typename Head, typename Tail>
34         struct alternates_list
35           : fusion::cons<Head, Tail>
36         {
37             BOOST_STATIC_CONSTANT(std::size_t, width = Head::width == Tail::width ? Head::width : detail::unknown_width::value);
38             BOOST_STATIC_CONSTANT(bool, pure = Head::pure && Tail::pure);
39 
alternates_listboost::xpressive::detail::alternates_list40             alternates_list(Head const &head, Tail const &tail)
41               : fusion::cons<Head, Tail>(head, tail)
42             {
43             }
44         };
45 
46         template<typename Head>
47         struct alternates_list<Head, fusion::nil>
48           : fusion::cons<Head, fusion::nil>
49         {
50             BOOST_STATIC_CONSTANT(std::size_t, width = Head::width);
51             BOOST_STATIC_CONSTANT(bool, pure = Head::pure);
52 
alternates_listboost::xpressive::detail::alternates_list53             alternates_list(Head const &head, fusion::nil const &tail)
54               : fusion::cons<Head, fusion::nil>(head, tail)
55             {
56             }
57         };
58     }
59 
60     namespace grammar_detail
61     {
62         ///////////////////////////////////////////////////////////////////////////////
63         // in_alternate_list
64         template<typename Grammar>
65         struct in_alternate_list : proto::callable
66         {
67             template<typename Sig> struct result {};
68 
69             template<typename This, typename Expr, typename State, typename Visitor>
70             struct result<This(Expr, State, Visitor)>
71             {
72                 typedef detail::alternates_list<
73                     typename Grammar::template result<void(Expr, detail::alternate_end_xpression, Visitor)>::type
74                   , State
75                 > type;
76             };
77 
78             template<typename Expr, typename State, typename Visitor>
79             typename result<void(Expr, State, Visitor)>::type
operator ()boost::xpressive::grammar_detail::in_alternate_list80             operator ()(Expr const &expr, State const &state, Visitor &visitor) const
81             {
82                 return typename result<void(Expr, State, Visitor)>::type(
83                     Grammar()(expr, detail::alternate_end_xpression(), visitor)
84                   , state
85                 );
86             }
87         };
88 
89         ///////////////////////////////////////////////////////////////////////////////
90         // as_alternate_matcher
91         template<typename Grammar>
92         struct as_alternate_matcher : proto::callable
93         {
94             template<typename Sig> struct result {};
95 
96             template<typename This, typename Expr, typename State, typename Visitor>
97             struct result<This(Expr, State, Visitor)>
98             {
99                 typedef detail::alternate_matcher<
100                     typename Grammar::template result<void(Expr, State, Visitor)>::type
101                   , typename Visitor::traits_type
102                 > type;
103             };
104 
105             template<typename Expr, typename State, typename Visitor>
106             typename result<void(Expr, State, Visitor)>::type
operator ()boost::xpressive::grammar_detail::as_alternate_matcher107             operator ()(Expr const &expr, State const &state, Visitor &visitor) const
108             {
109                 return typename result<void(Expr, State, Visitor)>::type(
110                     Grammar()(expr, state, visitor)
111                 );
112             }
113         };
114 
115     }
116 
117 }}
118 
119 #endif
120