PageRenderTime 54ms CodeModel.GetById 11ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/repository/home/qi/directive/kwd.hpp

http://hadesmem.googlecode.com/
C++ Header | 588 lines | 442 code | 92 blank | 54 comment | 16 complexity | 2aa45a506ae27c86dba12e802026334d MD5 | raw file
  1/*=============================================================================
  2    Copyright (c) 2001-2011 Joel de Guzman
  3    Copyright (c) 2011 Thomas Bernard
  4
  5    Distributed under the Boost Software License, Version 1.0. (See accompanying
  6    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7=============================================================================*/
  8#if !defined(SPIRIT_KWD_NOVEMBER_14_2008_1148AM)
  9#define SPIRIT_KWD_NOVEMBER_14_2008_1148AM
 10
 11#if defined(_MSC_VER)
 12#pragma once
 13#endif
 14
 15#include <boost/spirit/home/qi/meta_compiler.hpp>
 16#include <boost/spirit/home/qi/parser.hpp>
 17#include <boost/spirit/home/qi/auxiliary/lazy.hpp>
 18#include <boost/spirit/home/qi/operator/kleene.hpp>
 19#include <boost/spirit/home/support/container.hpp>
 20#include <boost/spirit/home/qi/detail/attributes.hpp>
 21#include <boost/spirit/home/qi/detail/fail_function.hpp>
 22#include <boost/spirit/home/support/info.hpp>
 23#include <boost/spirit/repository/home/support/kwd.hpp>
 24#include <boost/fusion/include/at.hpp>
 25#include <boost/foreach.hpp>
 26#include <vector>
 27
 28namespace boost { namespace spirit
 29{
 30    ///////////////////////////////////////////////////////////////////////////
 31    // Enablers
 32    ///////////////////////////////////////////////////////////////////////////
 33         
 34    template < typename T>
 35    struct use_directive<qi::domain
 36      , terminal_ex<repository::tag::kwd                     // enables kwd(key)[p]
 37        , fusion::vector1<T > >
 38    > : traits::is_string<T> {};
 39    
 40    template < typename T>
 41    struct use_directive<qi::domain
 42      , terminal_ex<repository::tag::ikwd                     // enables ikwd(key)[p]
 43        , fusion::vector1<T > >
 44    > : traits::is_string<T> {};
 45    
 46    
 47    template < typename T1, typename T2>
 48    struct use_directive<qi::domain
 49      , terminal_ex<repository::tag::kwd                     // enables kwd(key,exact)[p]
 50        , fusion::vector2< T1, T2 > >
 51    > : traits::is_string<T1> {};
 52
 53    template < typename T1, typename T2>
 54    struct use_directive<qi::domain
 55      , terminal_ex<repository::tag::ikwd                     // enables ikwd(key,exact)[p]
 56        , fusion::vector2< T1, T2 > >
 57    > : traits::is_string<T1> {};
 58
 59    template < typename T1, typename T2>
 60    struct use_directive<qi::domain
 61      , terminal_ex<repository::tag::kwd                     // enables kwd(min, max)[p]
 62        , fusion::vector3< T1, T2, T2 > >
 63    > : traits::is_string<T1> {};
 64
 65    template < typename T1, typename T2>
 66    struct use_directive<qi::domain
 67      , terminal_ex<repository::tag::ikwd                     // enables ikwd(min, max)[p]
 68        , fusion::vector3< T1, T2, T2 > >
 69    > : traits::is_string<T1> {};
 70
 71    template < typename T1, typename T2>
 72    struct use_directive<qi::domain
 73      , terminal_ex<repository::tag::kwd                     // enables kwd(min, inf)[p]
 74        , fusion::vector3<T1, T2, inf_type > >
 75    > : traits::is_string<T1> {};
 76    
 77    template < typename T1, typename T2>
 78    struct use_directive<qi::domain
 79      , terminal_ex<repository::tag::ikwd                     // enables ikwd(min, inf)[p]
 80        , fusion::vector3<T1, T2, inf_type > >
 81    > : traits::is_string<T1> {};
 82
 83
 84  /*  template <>                                     // enables *lazy* kwd(exact)[p]
 85    struct use_lazy_directive<
 86        qi::domain
 87      , tag::kwd
 88      , 1 // arity
 89    > : mpl::true_ {};
 90
 91    template <>                                     // enables *lazy* kwd(min, max)[p]
 92    struct use_lazy_directive<                      // and kwd(min, inf)[p]
 93        qi::domain
 94      , tag::kwd
 95      , 2 // arity
 96    > : mpl::true_ {};
 97*/
 98
 99}}
100
101namespace boost { namespace spirit { namespace repository { namespace qi
102{
103    using repository::kwd;
104    using repository::ikwd;
105    using spirit::inf;
106    using spirit::inf_type;
107
108template <typename T>
109    struct kwd_pass_iterator // handles kwd(exact)[p]
110    {
111        kwd_pass_iterator() {}
112        bool flag_init() const { return true; }
113        bool register_successful_parse(bool &flag,T &i) const {
114            flag=true;
115            return true;
116        }
117        
118
119    private:
120        // silence MSVC warning C4512: assignment operator could not be generated
121        kwd_pass_iterator& operator= (kwd_pass_iterator const&);
122    };
123
124    template <typename T>
125    struct kwd_exact_iterator // handles kwd(exact)[p]
126    {
127        kwd_exact_iterator(T const exact)
128          : exact(exact){}
129
130        typedef T type;
131        bool flag_init() const { return false; }
132        bool register_successful_parse(bool &flag,T &i) const {
133            i++;
134            if(i<exact)
135            {
136                flag=false;
137                return true;
138            }
139            else if(i==exact)
140            {
141                flag=true;
142                return true;
143            }
144            else
145                return flag=false;
146            
147        }
148        T const exact;
149
150    private:
151        // silence MSVC warning C4512: assignment operator could not be generated
152        kwd_exact_iterator& operator= (kwd_exact_iterator const&);
153    };
154
155    template <typename T>
156    struct kwd_finite_iterator // handles kwd(min, max)[p]
157    {
158        kwd_finite_iterator(T const min, T const max)
159          : min BOOST_PREVENT_MACRO_SUBSTITUTION (min)
160          , max BOOST_PREVENT_MACRO_SUBSTITUTION (max)
161            {}
162
163        typedef T type;
164        bool flag_init() const { return min==0; }
165        bool register_successful_parse(bool &flag,T &i) const {
166            i++;
167            if(i<min)
168            {
169                flag=false;
170                return true;
171            }
172            else if(i>=min && i<=max)
173            {
174                return flag=true;
175            }
176            else
177                return flag=false;
178        }
179        T const min;
180        T const max;
181
182    private:
183        // silence MSVC warning C4512: assignment operator could not be generated
184        kwd_finite_iterator& operator= (kwd_finite_iterator const&);
185    };
186
187    template <typename T>
188    struct kwd_infinite_iterator // handles kwd(min, inf)[p]
189    {
190        kwd_infinite_iterator(T const min)
191          : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) {}
192
193        typedef T type;
194        bool flag_init() const { return min==0; }
195        bool register_successful_parse(bool &flag,T &i) const {
196            i++;
197            flag = i>=min;
198            return true;
199        }
200        T const min;
201
202    private:
203        // silence MSVC warning C4512: assignment operator could not be generated
204        kwd_infinite_iterator& operator= (kwd_infinite_iterator const&);
205    };
206
207    // This class enables the transportation of parameters needed to call 
208    // the occurence constraint checker from higher level calls
209    // It also serves to select the correct parse function call 
210    // of the keyword parser. The implementation changes depending if it is
211    // called form a keyword parsing loop or not.
212    template <typename Skipper, typename NoCasePass>
213    struct skipper_keyword_marker
214    {
215        typedef NoCasePass no_case_pass;
216        
217        skipper_keyword_marker(Skipper const &skipper,bool &flag,int &counter) : 
218              skipper(skipper)
219            , flag(flag)
220            , counter(counter) 
221            {}
222            
223        const Skipper &skipper;
224        bool &flag;
225        int &counter;
226    };
227    
228    template <typename Subject, typename KeywordType, typename LoopIter , typename NoCase >
229    struct kwd_parser : spirit::qi::unary_parser<kwd_parser<Subject, KeywordType, LoopIter , NoCase > >
230    {
231        struct kwd_parser_id;
232        
233        typedef Subject subject_type;
234        typedef NoCase no_case_keyword;
235                
236        typedef typename
237            remove_const<typename traits::char_type_of<KeywordType>::type>::type
238        char_type;
239        
240        typedef std::basic_string<char_type> keyword_type;
241        
242        template <typename Context, typename Iterator>
243        struct attribute
244        {
245            typedef typename
246            traits::build_std_vector<
247                typename traits::attribute_of<
248                Subject, Context, Iterator>::type
249                        >::type
250                type;
251        };
252        
253
254        kwd_parser(Subject const& subject
255           , typename add_reference<KeywordType>::type keyword
256           , LoopIter const& iter)
257          : subject(subject), iter(iter), keyword(keyword) {}    
258        
259        // Call the subject parser on a non container attribute
260        template <typename Iterator, typename Context
261          , typename Skipper, typename Attribute>
262        bool parse_impl(Iterator& first, Iterator const& last
263          , Context& context, Skipper const& skipper
264          , Attribute& attr,mpl::false_) const
265        {
266            return subject.parse(first,last,context,skipper,attr);
267        }
268    
269        // Call the subject parser on a container attribute
270        template <typename Iterator, typename Context
271          , typename Skipper, typename Attribute>
272        bool parse_impl(Iterator& first, Iterator const& last
273          , Context& context, Skipper const& skipper
274          , Attribute& attr,mpl::true_) const
275        {                   
276            
277            // synthesized attribute needs to be default constructed
278            typename traits::container_value<Attribute>::type val =
279                typename traits::container_value<Attribute>::type();
280
281            Iterator save = first;
282            bool r = subject.parse(first,last,context,skipper, val);
283            if (r)
284            {
285                // push the parsed value into our attribute
286                r = traits::push_back(attr, val);
287                if (!r)
288                    first = save;
289            }
290            return r;
291        }
292       
293       template <typename Iterator, typename Context
294          , typename Skipper, typename Attribute,typename NoCasePass>
295        bool parse(Iterator& first, Iterator const& last
296          , Context& context, skipper_keyword_marker<Skipper,NoCasePass> const& skipper
297          , Attribute &attr) const
298        {
299            
300            typedef typename traits::attribute_of<
301                Subject, Context, Iterator>::type
302                subject_attribute;
303            
304            typedef typename mpl::and_<
305             traits::is_container<Attribute>
306            , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
307            >::type predicate;
308            
309            if((no_case_keyword::value && NoCasePass::value) || !NoCasePass::value)
310            {
311                if(parse_impl(first,last,context,skipper.skipper,attr, predicate()))
312                    return iter.register_successful_parse(skipper.flag,skipper.counter);
313            }
314            return false;
315        }
316       
317        template <typename Iterator, typename Context
318          , typename Skipper, typename Attribute>
319        bool parse(Iterator& first, Iterator const& last
320          , Context& context, Skipper const& skipper
321          , Attribute& attr) const
322          {
323              typedef typename traits::attribute_of<
324                Subject, Context, Iterator>::type
325                subject_attribute;
326            
327            typedef typename mpl::and_<
328            traits::is_container<Attribute>
329            , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
330            >::type predicate;
331            
332            // Parse the keyword
333            bool flag = iter.flag_init();
334            int counter = 0;
335            Iterator save = first;
336            spirit::qi::skip_over(first, last, skipper);
337            if(keyword.parse(first,last,context,skipper,unused)){
338                // Followed by the subject parser
339                spirit::qi::skip_over(first, last, skipper);
340                if(parse_impl(first,last,context,skipper,attr, predicate()))
341                {
342                    return iter.register_successful_parse(flag,counter);
343                }
344            }
345            first = save;            
346            return flag;            
347          }
348       
349    
350        template <typename Context>
351        info what(Context& context) const
352        {
353            if(no_case_keyword::value)
354                return info("ikwd", subject.what(context));
355            else
356                return info("kwd", subject.what(context));
357        }
358
359        Subject subject;
360        LoopIter iter;            
361        
362        spirit::qi::literal_string<KeywordType, true> keyword;
363    private:
364        // silence MSVC warning C4512: assignment operator could not be generated
365        kwd_parser& operator= (kwd_parser const&);
366
367        template <typename Iterator, typename Context, typename Skipper>
368        static spirit::qi::detail::fail_function<Iterator, Context, Skipper>
369        fail_function(
370            Iterator& first, Iterator const& last
371          , Context& context, Skipper const& skipper)
372        {
373            return spirit::qi::detail::fail_function<Iterator, Context, Skipper>
374                (first, last, context, skipper);
375        }
376
377
378    };
379}}}}
380
381///////////////////////////////////////////////////////////////////////////////
382namespace boost { namespace spirit { namespace qi
383{
384
385    ///////////////////////////////////////////////////////////////////////////
386    // Parser generators: make_xxx function (objects)
387    ///////////////////////////////////////////////////////////////////////////
388    
389     // Directive kwd(key)[p]
390    template <typename T1,  typename Subject, typename Modifiers>
391    struct make_directive<
392        terminal_ex<repository::tag::kwd, fusion::vector1<T1> >, Subject, Modifiers>
393    {
394        typedef typename add_const<T1>::type const_keyword;
395        typedef repository::qi::kwd_pass_iterator<int> iterator_type;
396        typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
397        
398                
399        typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
400
401        template <typename Terminal>
402        result_type operator()(
403            Terminal const& term, Subject const& subject, unused_type) const
404        {
405            return result_type(subject
406                        ,fusion::at_c<0>(term.args)
407                        ,iterator_type()
408                        );
409        }
410    };
411    
412    // Directive ikwd(key)[p]
413    template <typename T1,  typename Subject, typename Modifiers>
414    struct make_directive<
415        terminal_ex<repository::tag::ikwd, fusion::vector1<T1> >, Subject, Modifiers>
416    {
417        typedef typename add_const<T1>::type const_keyword;
418        typedef repository::qi::kwd_pass_iterator<int> iterator_type;
419        
420        typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
421
422        template <typename Terminal>
423        result_type operator()(
424            Terminal const& term, Subject const& subject, unused_type) const
425        {
426       /*     typename spirit::detail::get_encoding<Modifiers,
427                spirit::char_encoding::standard>::type encoding;*/
428                
429            return result_type(subject
430                        ,fusion::at_c<0>(term.args)
431                        ,iterator_type()                        
432                        );
433        }
434    };
435    
436    // Directive kwd(key,exact)[p]
437    template <typename T1, typename T2,  typename Subject, typename Modifiers>
438    struct make_directive<
439        terminal_ex<repository::tag::kwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
440    {
441        typedef typename add_const<T1>::type const_keyword;
442        typedef repository::qi::kwd_exact_iterator<T2> iterator_type;
443        typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
444        
445        typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
446
447        template <typename Terminal>
448        result_type operator()(
449            Terminal const& term, Subject const& subject, unused_type) const
450        {
451            return result_type(subject
452                        ,fusion::at_c<0>(term.args)
453                        ,fusion::at_c<1>(term.args)
454                        );
455        }
456    };
457
458    // Directive ikwd(key,exact)[p]
459    template <typename T1, typename T2,  typename Subject, typename Modifiers>
460    struct make_directive<
461        terminal_ex<repository::tag::ikwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
462    {
463        typedef typename add_const<T1>::type const_keyword;
464        typedef repository::qi::kwd_exact_iterator<T2> iterator_type;
465        
466        typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
467        
468        template <typename Terminal>
469        result_type operator()(
470            Terminal const& term, Subject const& subject, unused_type) const
471        {            
472            return result_type(subject
473                        , fusion::at_c<0>(term.args)
474                        , fusion::at_c<1>(term.args)
475                        );
476        }
477    };
478    
479    // Directive kwd(min, max)[p]
480    template <typename T1, typename T2, typename Subject, typename Modifiers>
481    struct make_directive<
482        terminal_ex<repository::tag::kwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
483    {
484        typedef typename add_const<T1>::type const_keyword;
485        typedef repository::qi::kwd_finite_iterator<T2> iterator_type;
486        typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
487                    
488        typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
489
490        template <typename Terminal>
491        result_type operator()(
492            Terminal const& term, Subject const& subject, unused_type) const
493        {
494            return result_type(subject, fusion::at_c<0>(term.args),
495                iterator_type(
496                    fusion::at_c<1>(term.args)
497                  , fusion::at_c<2>(term.args)
498                )
499            );
500        }
501    };
502
503    // Directive ikwd(min, max)[p]
504    template <typename T1, typename T2, typename Subject, typename Modifiers>
505    struct make_directive<
506        terminal_ex<repository::tag::ikwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
507    {
508        typedef typename add_const<T1>::type const_keyword;
509        typedef repository::qi::kwd_finite_iterator<T2> iterator_type;
510                
511        typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
512
513        template <typename Terminal>
514        result_type operator()(
515            Terminal const& term, Subject const& subject, unused_type) const
516        {
517        
518            return result_type(subject, fusion::at_c<0>(term.args),
519                iterator_type(
520                    fusion::at_c<1>(term.args)
521                  , fusion::at_c<2>(term.args)
522                )
523            );
524        }
525    };
526    
527    // Directive kwd(min, inf)[p]
528    template <typename T1, typename T2, typename Subject, typename Modifiers>
529    struct make_directive<
530        terminal_ex<repository::tag::kwd
531        , fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers>
532    {
533        typedef typename add_const<T1>::type const_keyword;
534        typedef repository::qi::kwd_infinite_iterator<T2> iterator_type;
535        typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
536        
537        typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
538
539        template <typename Terminal>
540        result_type operator()(
541            Terminal const& term, Subject const& subject, unused_type) const
542        {
543            return result_type(subject
544                , fusion::at_c<0>(term.args)
545                , fusion::at_c<1>(term.args)
546                );
547        }
548    };
549    
550    // Directive ikwd(min, inf)[p]
551    template <typename T1, typename T2, typename Subject, typename Modifiers>
552    struct make_directive<
553        terminal_ex<repository::tag::ikwd
554        , fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers>
555    {
556        typedef typename add_const<T1>::type const_keyword;
557        typedef repository::qi::kwd_infinite_iterator<T2> iterator_type;
558        
559        typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
560
561        template <typename Terminal>
562        result_type operator()(
563            Terminal const& term, Subject const& subject, unused_type) const
564        {
565            typename spirit::detail::get_encoding<Modifiers,
566                spirit::char_encoding::standard>::type encoding;
567                
568            return result_type(subject
569                , fusion::at_c<0>(term.args)
570                , fusion::at_c<1>(term.args)
571                );
572        }
573    };
574    
575    
576}}}
577
578namespace boost { namespace spirit { namespace traits
579{
580    template <typename Subject, typename KeywordType
581            , typename LoopIter, typename NoCase >
582    struct has_semantic_action< 
583            repository::qi::kwd_parser< Subject, KeywordType, LoopIter, NoCase > >
584      : unary_has_semantic_action<Subject> {};
585}}}
586
587#endif
588