summaryrefslogtreecommitdiff
path: root/boost/spirit/home/x3/char/char_set.hpp
blob: 1bff83ec6bd572af4aabdfacf6acfc6f924f4458 (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
136
/*=============================================================================
    Copyright (c) 2001-2014 Joel de Guzman

    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_CHAR_SET_OCT_12_2014_1051AM)
#define BOOST_SPIRIT_X3_CHAR_SET_OCT_12_2014_1051AM

#include <boost/spirit/home/x3/char/char_parser.hpp>
#include <boost/spirit/home/x3/char/detail/cast_char.hpp>
#include <boost/spirit/home/x3/support/traits/string_traits.hpp>
#include <boost/spirit/home/x3/support/utility/utf8.hpp>
#include <boost/spirit/home/x3/support/no_case.hpp>
#include <boost/spirit/home/support/char_set/basic_chset.hpp>

#include <boost/type_traits/is_same.hpp>

namespace boost { namespace spirit { namespace x3
{
    ///////////////////////////////////////////////////////////////////////////
    // Parser for a character range
    ///////////////////////////////////////////////////////////////////////////
    template <typename Encoding, typename Attribute = typename Encoding::char_type>
    struct char_range
      : char_parser< char_range<Encoding, Attribute> >
    {

        typedef typename Encoding::char_type char_type;
        typedef Encoding encoding;
        typedef Attribute attribute_type;
        static bool const has_attribute =
            !is_same<unused_type, attribute_type>::value;


        char_range(char_type from_, char_type to_)
          : from(from_), to(to_) {}

        template <typename Char, typename Context>
        bool test(Char ch_, Context& context) const
        {

            char_type ch = char_type(ch_);  // optimize for token based parsing
            return ((sizeof(Char) <= sizeof(char_type)) || encoding::ischar(ch_))
                        && (get_case_compare<encoding>(context)(ch, from) >= 0 )
                        && (get_case_compare<encoding>(context)(ch , to) <= 0 );
        }

        char_type from, to;
    };


    ///////////////////////////////////////////////////////////////////////////
    // Parser for a character set
    ///////////////////////////////////////////////////////////////////////////
    template <typename Encoding, typename Attribute = typename Encoding::char_type>
    struct char_set : char_parser<char_set<Encoding, Attribute>>
    {
        typedef typename Encoding::char_type char_type;
        typedef Encoding encoding;
        typedef Attribute attribute_type;
        static bool const has_attribute =
            !is_same<unused_type, attribute_type>::value;

        template <typename String>
        char_set(String const& str)
        {
            using spirit::x3::detail::cast_char;

            typedef typename
                remove_const<
                    typename traits::char_type_of<String>::type
                >::type
            in_type;

            in_type const* definition =
                (in_type const*)traits::get_c_string(str);
            in_type ch = *definition++;
            while (ch)
            {
                in_type next = *definition++;
                if (next == '-')
                {
                    next = *definition++;
                    if (next == 0)
                    {
                        chset.set(cast_char<char_type>(ch));
                        chset.set('-');
                        break;
                    }
                    chset.set(
                        cast_char<char_type>(ch),
                        cast_char<char_type>(next)
                    );
                }
                else
                {
                    chset.set(cast_char<char_type>(ch));
                }
                ch = next;
            }
        }

        template <typename Char, typename Context>
        bool test(Char ch_, Context const& context) const
        {
            return ((sizeof(Char) <= sizeof(char_type)) || encoding::ischar(ch_))
                && get_case_compare<encoding>(context).in_set(ch_,chset);
        }

        support::detail::basic_chset<char_type> chset;
    };

    template <typename Encoding, typename Attribute>
    struct get_info<char_set<Encoding, Attribute>>
    {
        typedef std::string result_type;
        std::string operator()(char_set<Encoding, Attribute> const& /* p */) const
        {
            return "char-set";
        }
    };

    template <typename Encoding, typename Attribute>
    struct get_info<char_range<Encoding, Attribute>>
    {
        typedef std::string result_type;
        std::string operator()(char_range<Encoding, Attribute> const& p) const
        {
            return "char_range \"" + to_utf8(Encoding::toucs4(p.from)) + '-' + to_utf8(Encoding::toucs4(p.to))+ '"';
        }
    };

}}}

#endif