summaryrefslogtreecommitdiff
path: root/boost/spirit/home/x3/auxiliary/attr.hpp
blob: 5b3c7a5d8530042730f49315559fe4dec19d87a9 (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
/*=============================================================================
    Copyright (c) 2001-2011 Hartmut Kaiser
    Copyright (c) 2001-2014 Joel de Guzman
    Copyright (c) 2013 Agustin Berge

    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)
==============================================================================*/
#ifndef BOOST_SPIRIT_X3_ATTR_JUL_23_2008_0956AM
#define BOOST_SPIRIT_X3_ATTR_JUL_23_2008_0956AM

#include <boost/spirit/home/x3/core/parser.hpp>
#include <boost/spirit/home/x3/support/unused.hpp>
#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <algorithm>
#include <cstddef>
#include <string>
#include <utility>

namespace boost { namespace spirit { namespace x3
{
    template <typename Value>
    struct attr_parser : parser<attr_parser<Value>>
    {
        typedef Value attribute_type;

        static bool const has_attribute =
            !is_same<unused_type, attribute_type>::value;
        static bool const handles_container =
            traits::is_container<attribute_type>::value;
        
        attr_parser(Value const& value)
          : value_(value) {}
        attr_parser(Value&& value)
          : value_(std::move(value)) {}

        template <typename Iterator, typename Context
          , typename RuleContext, typename Attribute>
        bool parse(Iterator& first, Iterator const& last
          , Context const& context, RuleContext&, Attribute& attr_) const
        {
            // $$$ Change to copy_to once we have it $$$
            traits::move_to(value_, attr_);
            return true;
        }

        Value value_;

    private:
        // silence MSVC warning C4512: assignment operator could not be generated
        attr_parser& operator= (attr_parser const&);
    };
    
    template <typename Value, std::size_t N>
    struct attr_parser<Value[N]> : parser<attr_parser<Value[N]>>
    {
        typedef Value attribute_type[N];

        static bool const has_attribute =
            !is_same<unused_type, attribute_type>::value;
        static bool const handles_container = true;
        
        attr_parser(Value const (&value)[N])
        {
            std::copy(value + 0, value + N, value_ + 0);
        }

        attr_parser(Value (&&value)[N])
        {
            std::move(value + 0, value + N, value_ + 0);
        }

        template <typename Iterator, typename Context
          , typename RuleContext, typename Attribute>
        bool parse(Iterator& first, Iterator const& last
          , Context const& context, RuleContext&, Attribute& attr_) const
        {
            // $$$ Change to copy_to once we have it $$$
            traits::move_to(value_ + 0, value_ + N, attr_);
            return true;
        }

        Value value_[N];

    private:
        // silence MSVC warning C4512: assignment operator could not be generated
        attr_parser& operator= (attr_parser const&);
    };
    
    template <typename Value>
    struct get_info<attr_parser<Value>>
    {
        typedef std::string result_type;
        std::string operator()(attr_parser<Value> const& /*p*/) const
        {
            return "attr";
        }
    };

    struct attr_gen
    {
        template <typename Value>
        attr_parser<typename remove_cv<
            typename remove_reference<Value>::type>::type>
        operator()(Value&& value) const
        {
            return { std::forward<Value>(value) };
        }
        
        template <typename Value, std::size_t N>
        attr_parser<typename remove_cv<Value>::type[N]>
        operator()(Value (&value)[N]) const
        {
            return { value };
        }
        template <typename Value, std::size_t N>
        attr_parser<typename remove_cv<Value>::type[N]>
        operator()(Value (&&value)[N]) const
        {
            return { value };
        }
    };

    auto const attr = attr_gen{};
}}}

#endif