• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2001-2011 Hartmut Kaiser
4     Copyright (c) 2014 Thomas Bernard
5 
6     Distributed under the Boost Software License, Version 1.0. (See accompanying
7     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 ==============================================================================*/
9 #ifndef BOOST_SPIRIT_X3_DIRECTIVE_REPEAT_HPP
10 #define BOOST_SPIRIT_X3_DIRECTIVE_REPEAT_HPP
11 
12 #include <boost/spirit/home/x3/core/parser.hpp>
13 #include <boost/spirit/home/x3/operator/kleene.hpp>
14 
15 namespace boost { namespace spirit { namespace x3 { namespace detail
16 {
17     template <typename T>
18     struct exact_count // handles repeat(exact)[p]
19     {
20         typedef T type;
got_maxboost::spirit::x3::detail::exact_count21         bool got_max(T i) const { return i >= exact_value; }
got_minboost::spirit::x3::detail::exact_count22         bool got_min(T i) const { return i >= exact_value; }
23 
24         T const exact_value;
25     };
26 
27     template <typename T>
28     struct finite_count // handles repeat(min, max)[p]
29     {
30         typedef T type;
got_maxboost::spirit::x3::detail::finite_count31         bool got_max(T i) const { return i >= max_value; }
got_minboost::spirit::x3::detail::finite_count32         bool got_min(T i) const { return i >= min_value; }
33 
34         T const min_value;
35         T const max_value;
36     };
37 
38     template <typename T>
39     struct infinite_count // handles repeat(min, inf)[p]
40     {
41         typedef T type;
got_maxboost::spirit::x3::detail::infinite_count42         bool got_max(T /*i*/) const { return false; }
got_minboost::spirit::x3::detail::infinite_count43         bool got_min(T i) const { return i >= min_value; }
44 
45         T const min_value;
46     };
47 }}}}
48 
49 namespace boost { namespace spirit { namespace x3
50 {
51     template<typename Subject, typename RepeatCountLimit>
52     struct repeat_directive : unary_parser<Subject, repeat_directive<Subject,RepeatCountLimit>>
53     {
54         typedef unary_parser<Subject, repeat_directive<Subject,RepeatCountLimit>> base_type;
55         static bool const is_pass_through_unary = true;
56         static bool const handles_container = true;
57 
repeat_directiveboost::spirit::x3::repeat_directive58         constexpr repeat_directive(Subject const& subject, RepeatCountLimit const& repeat_limit_)
59           : base_type(subject)
60           , repeat_limit(repeat_limit_)
61         {}
62 
63         template<typename Iterator, typename Context
64           , typename RContext, typename Attribute>
parseboost::spirit::x3::repeat_directive65         bool parse(
66             Iterator& first, Iterator const& last
67           , Context const& context, RContext& rcontext, Attribute& attr) const
68         {
69             Iterator local_iterator = first;
70             typename RepeatCountLimit::type i{};
71             for (/**/; !repeat_limit.got_min(i); ++i)
72             {
73                 if (!detail::parse_into_container(
74                       this->subject, local_iterator, last, context, rcontext, attr))
75                     return false;
76             }
77 
78             first = local_iterator;
79             // parse some more up to the maximum specified
80             for (/**/; !repeat_limit.got_max(i); ++i)
81             {
82                 if (!detail::parse_into_container(
83                       this->subject, first, last, context, rcontext, attr))
84                     break;
85             }
86             return true;
87         }
88 
89         RepeatCountLimit repeat_limit;
90     };
91 
92     // Infinite loop tag type
93     struct inf_type {};
94     constexpr inf_type inf = inf_type();
95 
96     struct repeat_gen
97     {
98         template<typename Subject>
operator []boost::spirit::x3::repeat_gen99         constexpr auto operator[](Subject const& subject) const
100         {
101             return *as_parser(subject);
102         }
103 
104         template <typename T>
105         struct repeat_gen_lvl1
106         {
repeat_gen_lvl1boost::spirit::x3::repeat_gen::repeat_gen_lvl1107             constexpr repeat_gen_lvl1(T&& repeat_limit_)
108               : repeat_limit(repeat_limit_)
109             {}
110 
111             template<typename Subject>
112             constexpr repeat_directive< typename extension::as_parser<Subject>::value_type, T>
operator []boost::spirit::x3::repeat_gen::repeat_gen_lvl1113             operator[](Subject const& subject) const
114             {
115                 return { as_parser(subject),repeat_limit };
116             }
117 
118             T repeat_limit;
119         };
120 
121         template <typename T>
122         constexpr repeat_gen_lvl1<detail::exact_count<T>>
operator ()boost::spirit::x3::repeat_gen123         operator()(T const exact) const
124         {
125             return { detail::exact_count<T>{exact} };
126         }
127 
128         template <typename T>
129         constexpr repeat_gen_lvl1<detail::finite_count<T>>
operator ()boost::spirit::x3::repeat_gen130         operator()(T const min_val, T const max_val) const
131         {
132             return { detail::finite_count<T>{min_val,max_val} };
133         }
134 
135         template <typename T>
136         constexpr repeat_gen_lvl1<detail::infinite_count<T>>
operator ()boost::spirit::x3::repeat_gen137         operator()(T const min_val, inf_type const &) const
138         {
139             return { detail::infinite_count<T>{min_val} };
140         }
141     };
142 
143     constexpr auto repeat = repeat_gen{};
144 }}}
145 
146 namespace boost { namespace spirit { namespace x3 { namespace traits
147 {
148     template <typename Subject, typename RepeatCountLimit, typename Context>
149     struct attribute_of<x3::repeat_directive<Subject,RepeatCountLimit>, Context>
150       : build_container<typename attribute_of<Subject, Context>::type> {};
151 }}}}
152 
153 
154 #endif
155