summaryrefslogtreecommitdiff
path: root/boost/spirit/home/x3/support/context.hpp
blob: 93bcb240707914c639bc5745341583cd78c91e90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*=============================================================================
    Copyright (c) 2001-2014 Joel de Guzman
    http://spirit.sourceforge.net/

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(BOOST_SPIRIT_X3_CONTEXT_JAN_4_2012_1215PM)
#define BOOST_SPIRIT_X3_CONTEXT_JAN_4_2012_1215PM

#if defined(_MSC_VER)
#pragma once
#endif

#include <boost/spirit/home/x3/support/unused.hpp>
#include <boost/mpl/identity.hpp>

namespace boost { namespace spirit { namespace x3
{
    template <typename ID, typename T, typename Next = unused_type>
    struct context
    {
        context(T& val, Next const& next)
            : val(val), next(next) {}

        template <typename ID_, typename Unused = void>
        struct get_result
        {
            typedef typename Next::template get_result<ID_>::type type;
        };

        template <typename Unused>
        struct get_result<mpl::identity<ID>, Unused>
        {
            typedef T& type;
        };

        T& get(mpl::identity<ID>) const
        {
            return val;
        }

        template <typename ID_>
        typename Next::template get_result<ID_>::type
        get(ID_ id) const
        {
            return next.get(id);
        }

        T& val;
        Next const& next;
    };

    template <typename ID, typename T>
    struct context<ID, T, unused_type>
    {
        context(T& val)
            : val(val) {}

        context(T& val, unused_type)
            : val(val) {}

        template <typename ID_, typename Unused = void>
        struct get_result
        {
            typedef unused_type type;
        };

        template <typename Unused>
        struct get_result<mpl::identity<ID>, Unused>
        {
            typedef T& type;
        };

        T& get(mpl::identity<ID>) const
        {
            return val;
        }

        template <typename ID_>
        unused_type
        get(ID_) const
        {
            return unused;
        }

        T& val;
    };

    template <typename Tag, typename Context>
    inline auto
    get(Context const& context)
        -> decltype(context.get(mpl::identity<Tag>()))
    {
        return context.get(mpl::identity<Tag>());
    }

    template <typename ID, typename T, typename Next>
    inline context<ID, T, Next> make_context(T& val, Next const& next)
    {
        return context<ID, T, Next>(val, next);
    }

    template <typename ID, typename T>
    inline context<ID, T> make_context(T& val)
    {
        return context<ID, T>(val);
    }
    
    namespace detail
    {
        template <typename ID, typename T, typename Next, typename FoundVal>
        inline Next const&
        make_unique_context(T& val, Next const& next, FoundVal&)
        {
            return next;
        }
        
        template <typename ID, typename T, typename Next>
        inline context<ID, T, Next>
        make_unique_context(T& val, Next const& next, unused_type)
        {
            return context<ID, T, Next>(val, next);
        }
    }
    
    template <typename ID, typename T, typename Next>
    inline auto
    make_unique_context(T& val, Next const& next)
    {
        return detail::make_unique_context<ID>(val, next, x3::get<ID>(next));
    }
}}}

#endif