File indexing completed on 2025-01-19 09:47:44
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_SPIRIT_QI_DIRECTIVE_REPEAT_HPP
0009 #define BOOST_SPIRIT_QI_DIRECTIVE_REPEAT_HPP
0010
0011 #if defined(_MSC_VER)
0012 #pragma once
0013 #endif
0014
0015 #include <boost/spirit/home/qi/meta_compiler.hpp>
0016 #include <boost/spirit/home/qi/parser.hpp>
0017 #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
0018 #include <boost/spirit/home/qi/operator/kleene.hpp>
0019 #include <boost/spirit/home/support/container.hpp>
0020 #include <boost/spirit/home/support/common_terminals.hpp>
0021 #include <boost/spirit/home/qi/detail/attributes.hpp>
0022 #include <boost/spirit/home/qi/detail/fail_function.hpp>
0023 #include <boost/spirit/home/qi/detail/pass_container.hpp>
0024 #include <boost/spirit/home/support/info.hpp>
0025 #include <boost/spirit/home/support/has_semantic_action.hpp>
0026 #include <boost/spirit/home/support/handles_container.hpp>
0027 #include <boost/fusion/include/at.hpp>
0028 #include <vector>
0029
0030 namespace boost { namespace spirit
0031 {
0032
0033
0034
0035 template <>
0036 struct use_directive<qi::domain, tag::repeat>
0037 : mpl::true_ {};
0038
0039 template <typename T>
0040 struct use_directive<qi::domain
0041 , terminal_ex<tag::repeat
0042 , fusion::vector1<T> >
0043 > : mpl::true_ {};
0044
0045 template <typename T>
0046 struct use_directive<qi::domain
0047 , terminal_ex<tag::repeat
0048 , fusion::vector2<T, T> >
0049 > : mpl::true_ {};
0050
0051 template <typename T>
0052 struct use_directive<qi::domain
0053 , terminal_ex<tag::repeat
0054 , fusion::vector2<T, inf_type> >
0055 > : mpl::true_ {};
0056
0057 template <>
0058 struct use_lazy_directive<
0059 qi::domain
0060 , tag::repeat
0061 , 1
0062 > : mpl::true_ {};
0063
0064 template <>
0065 struct use_lazy_directive<
0066 qi::domain
0067 , tag::repeat
0068 , 2
0069 > : mpl::true_ {};
0070 }}
0071
0072 namespace boost { namespace spirit { namespace qi
0073 {
0074 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0075 using spirit::repeat;
0076 using spirit::inf;
0077 #endif
0078 using spirit::repeat_type;
0079 using spirit::inf_type;
0080
0081 #ifdef _MSC_VER
0082 # pragma warning(push)
0083 # pragma warning(disable: 4512)
0084 #endif
0085 template <typename T>
0086 struct exact_iterator
0087 {
0088 exact_iterator(T const exact_)
0089 : exact(exact_) {}
0090
0091 typedef T type;
0092 T start() const { return 0; }
0093 bool got_max(T i) const { return i >= exact; }
0094 bool got_min(T i) const { return i >= exact; }
0095
0096 T const exact;
0097 };
0098
0099 template <typename T>
0100 struct finite_iterator
0101 {
0102 finite_iterator(T const min_, T const max_)
0103 : min BOOST_PREVENT_MACRO_SUBSTITUTION (min_)
0104 , max BOOST_PREVENT_MACRO_SUBSTITUTION (max_) {}
0105
0106 typedef T type;
0107 T start() const { return 0; }
0108 bool got_max(T i) const { return i >= max; }
0109 bool got_min(T i) const { return i >= min; }
0110
0111 T const min;
0112 T const max;
0113 };
0114
0115 template <typename T>
0116 struct infinite_iterator
0117 {
0118 infinite_iterator(T const min_)
0119 : min BOOST_PREVENT_MACRO_SUBSTITUTION (min_) {}
0120
0121 typedef T type;
0122 T start() const { return 0; }
0123 bool got_max(T ) const { return false; }
0124 bool got_min(T i) const { return i >= min; }
0125
0126 T const min;
0127 };
0128 #ifdef _MSC_VER
0129 # pragma warning(pop)
0130 #endif
0131
0132 template <typename Subject, typename LoopIter>
0133 struct repeat_parser : unary_parser<repeat_parser<Subject, LoopIter> >
0134 {
0135 typedef Subject subject_type;
0136
0137 template <typename Context, typename Iterator>
0138 struct attribute
0139 {
0140
0141
0142
0143 typedef typename
0144 traits::build_std_vector<
0145 typename traits::attribute_of<
0146 Subject, Context, Iterator>::type
0147 >::type
0148 type;
0149 };
0150
0151 repeat_parser(Subject const& subject_, LoopIter const& iter_)
0152 : subject(subject_), iter(iter_) {}
0153
0154 template <typename F>
0155 bool parse_container(F f) const
0156 {
0157 typename LoopIter::type i = iter.start();
0158 for (; !iter.got_min(i); ++i)
0159 {
0160 if (f (subject))
0161 return false;
0162 }
0163
0164
0165 typename F::iterator_type save = f.f.first;
0166 for (; !iter.got_max(i); ++i)
0167 {
0168 if (f (subject))
0169 break;
0170 save = f.f.first;
0171 }
0172
0173 f.f.first = save;
0174 return true;
0175 }
0176
0177 template <typename Iterator, typename Context
0178 , typename Skipper, typename Attribute>
0179 bool parse(Iterator& first, Iterator const& last
0180 , Context& context, Skipper const& skipper
0181 , Attribute& attr_) const
0182 {
0183 typedef detail::fail_function<Iterator, Context, Skipper>
0184 fail_function;
0185
0186
0187 traits::make_container(attr_);
0188
0189 Iterator iter_local = first;
0190 fail_function f(iter_local, last, context, skipper);
0191 if (!parse_container(detail::make_pass_container(f, attr_)))
0192 return false;
0193
0194 first = f.first;
0195 return true;
0196 }
0197
0198 template <typename Context>
0199 info what(Context& context) const
0200 {
0201 return info("repeat", subject.what(context));
0202 }
0203
0204 Subject subject;
0205 LoopIter iter;
0206 };
0207
0208
0209
0210
0211 template <typename Subject, typename Modifiers>
0212 struct make_directive<tag::repeat, Subject, Modifiers>
0213 {
0214 typedef kleene<Subject> result_type;
0215 result_type operator()(unused_type, Subject const& subject, unused_type) const
0216 {
0217 return result_type(subject);
0218 }
0219 };
0220
0221 template <typename T, typename Subject, typename Modifiers>
0222 struct make_directive<
0223 terminal_ex<tag::repeat, fusion::vector1<T> >, Subject, Modifiers>
0224 {
0225 typedef exact_iterator<T> iterator_type;
0226 typedef repeat_parser<Subject, iterator_type> result_type;
0227
0228 template <typename Terminal>
0229 result_type operator()(
0230 Terminal const& term, Subject const& subject, unused_type) const
0231 {
0232 return result_type(subject, fusion::at_c<0>(term.args));
0233 }
0234 };
0235
0236 template <typename T, typename Subject, typename Modifiers>
0237 struct make_directive<
0238 terminal_ex<tag::repeat, fusion::vector2<T, T> >, Subject, Modifiers>
0239 {
0240 typedef finite_iterator<T> iterator_type;
0241 typedef repeat_parser<Subject, iterator_type> result_type;
0242
0243 template <typename Terminal>
0244 result_type operator()(
0245 Terminal const& term, Subject const& subject, unused_type) const
0246 {
0247 return result_type(subject,
0248 iterator_type(
0249 fusion::at_c<0>(term.args)
0250 , fusion::at_c<1>(term.args)
0251 )
0252 );
0253 }
0254 };
0255
0256 template <typename T, typename Subject, typename Modifiers>
0257 struct make_directive<
0258 terminal_ex<tag::repeat
0259 , fusion::vector2<T, inf_type> >, Subject, Modifiers>
0260 {
0261 typedef infinite_iterator<T> iterator_type;
0262 typedef repeat_parser<Subject, iterator_type> result_type;
0263
0264 template <typename Terminal>
0265 result_type operator()(
0266 Terminal const& term, Subject const& subject, unused_type) const
0267 {
0268 return result_type(subject, fusion::at_c<0>(term.args));
0269 }
0270 };
0271 }}}
0272
0273 namespace boost { namespace spirit { namespace traits
0274 {
0275
0276 template <typename Subject, typename LoopIter>
0277 struct has_semantic_action<qi::repeat_parser<Subject, LoopIter> >
0278 : unary_has_semantic_action<Subject> {};
0279
0280
0281 template <typename Subject, typename LoopIter, typename Attribute
0282 , typename Context, typename Iterator>
0283 struct handles_container<qi::repeat_parser<Subject, LoopIter>
0284 , Attribute, Context, Iterator>
0285 : mpl::true_ {};
0286 }}}
0287
0288 #endif