summaryrefslogtreecommitdiff
path: root/boost/spirit/repository/home/qi/primitive/advance.hpp
blob: 11a74bbb1363ad9f42805cef8ee14080e00111da (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
//  Copyright (c) 2011 Aaron Graham
//
//  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_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM)
#define BOOST_SPIRIT_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM

#include <boost/spirit/include/qi_parse.hpp>

///////////////////////////////////////////////////////////////////////////////
// definition the place holder
namespace boost { namespace spirit { namespace repository { namespace qi
{
    BOOST_SPIRIT_TERMINAL_EX(advance);
}}}}

///////////////////////////////////////////////////////////////////////////////
// implementation the enabler
namespace boost { namespace spirit
{
    template <typename A0>
    struct use_terminal<qi::domain
      , terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> > >
      : mpl::or_<is_integral<A0>, is_enum<A0> >
    {};

    template <>
    struct use_lazy_terminal<qi::domain, repository::qi::tag::advance, 1>
      : mpl::true_
    {};
}}

///////////////////////////////////////////////////////////////////////////////
// implementation of the parser
namespace boost { namespace spirit { namespace repository { namespace qi
{
    template <typename Int>
    struct advance_parser
      : boost::spirit::qi::primitive_parser< advance_parser<Int> >
    {
        // Define the attribute type exposed by this parser component
        template <typename Context, typename Iterator>
        struct attribute
        {
            typedef boost::spirit::unused_type type;
        };

        advance_parser(Int dist)
          : dist(dist)
        {}

        // This function is called during the actual parsing process
        template <typename Iterator, typename Context
            , typename Skipper, typename Attribute>
        bool parse(Iterator& first, Iterator const& last
            , Context&, Skipper&, Attribute&) const
        {
            // This series of checks is designed to fail parsing on negative
            // values, without generating a "expression always evaluates true"
            // warning on unsigned types.
            if (dist == Int(0)) return true;
            if (dist < Int(1)) return false;

            typedef typename std::iterator_traits<Iterator>::iterator_category
                iterator_category;
            return advance(first, last, iterator_category());
        }

        // This function is called during error handling to create
        // a human readable string for the error context.
        template <typename Context>
        boost::spirit::info what(Context&) const
        {
            return boost::spirit::info("advance");
        }

    private:
        // this is the general implementation used by most iterator categories
        template <typename Iterator, typename IteratorCategory>
        bool advance(Iterator& first, Iterator const& last
            , IteratorCategory) const
        {
            Int n = dist;
            Iterator i = first;
            while (n)
            {
                if (i == last) return false;
                ++i;
                --n;
            }
            first = i;
            return true;
        }

        // this is a specialization for random access iterators
        template <typename Iterator>
        bool advance(Iterator& first, Iterator const& last
            , std::random_access_iterator_tag) const
        {
            Iterator const it = first + dist;
            if (it > last) return false;
            first = it;
            return true;
        }

        Int const dist;
    };
}}}}

///////////////////////////////////////////////////////////////////////////////
// instantiation of the parser
namespace boost { namespace spirit { namespace qi
{
    template <typename Modifiers, typename A0>
    struct make_primitive<
          terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> >
        , Modifiers>
    {
        typedef repository::qi::advance_parser<A0> result_type;

        template <typename Terminal>
        result_type operator()(Terminal const& term, unused_type) const
        {
            return result_type(fusion::at_c<0>(term.args));
        }
    };
}}}

#endif