1 /*=============================================================================
2     Copyright (c) 2002-2003 Joel de Guzman
3     Copyright (c) 2002-2003 Martin Wille
4     http://spirit.sourceforge.net/
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_FOR_HPP
10 #define BOOST_SPIRIT_FOR_HPP
11 ////////////////////////////////////////////////////////////////////////////////
12 #include <boost/spirit/home/classic/namespace.hpp>
13 #include <boost/spirit/home/classic/core/parser.hpp>
14 #include <boost/spirit/home/classic/core/composite/composite.hpp>
15 #include <boost/spirit/home/classic/dynamic/impl/conditions.ipp>
16 
17 ////////////////////////////////////////////////////////////////////////////////
18 
19 namespace boost { namespace spirit {
20 
21 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
22 
23     namespace impl
24     {
25 
26         template <typename FuncT>
27         struct for_functor
28         {
29             typedef typename boost::call_traits<FuncT>::param_type  param_t;
30 
for_functorboost::spirit::impl::for_functor31             for_functor(param_t f) : func(f) {}
for_functorboost::spirit::impl::for_functor32             for_functor() {}
33             FuncT func;
34         };
35 
36         template <typename InitF>
37         struct for_init_functor : for_functor<InitF>
38         {
39             typedef for_functor<InitF>          base_t;
40             typedef typename base_t::param_t    param_t;
41 
for_init_functorboost::spirit::impl::for_init_functor42             for_init_functor(param_t f) : base_t(f) {}
for_init_functorboost::spirit::impl::for_init_functor43             for_init_functor() : base_t() {}
initboost::spirit::impl::for_init_functor44             void init() const { /*return*/ this->func(); }
45         };
46 
47         template <typename StepF>
48         struct for_step_functor : for_functor<StepF>
49         {
50             typedef for_functor<StepF>          base_t;
51             typedef typename base_t::param_t    param_t;
52 
for_step_functorboost::spirit::impl::for_step_functor53             for_step_functor(param_t f) : base_t(f) {}
for_step_functorboost::spirit::impl::for_step_functor54             for_step_functor() : base_t() {}
stepboost::spirit::impl::for_step_functor55             void step() const { /*return*/ this->func(); }
56         };
57 
58         //////////////////////////////////
59         // for_parser
60         template
61         <
62             typename InitF, typename CondT, typename StepF,
63             typename ParsableT
64         >
65         struct for_parser
66             : private for_init_functor<InitF>
67             , private for_step_functor<StepF>
68             , private condition_evaluator<typename as_parser<CondT>::type>
69             , public unary
70             <
71                 typename as_parser<ParsableT>::type,
72                 parser< for_parser<InitF, CondT, StepF, ParsableT> >
73             >
74         {
75             typedef for_parser<InitF, CondT, StepF, ParsableT> self_t;
76             typedef as_parser<CondT>                           cond_as_parser_t;
77             typedef typename cond_as_parser_t::type            condition_t;
78             typedef condition_evaluator<condition_t>           eval_t;
79             typedef as_parser<ParsableT>                       as_parser_t;
80             typedef typename as_parser_t::type                 parser_t;
81             typedef unary< parser_t, parser< self_t > >        base_t;
82 
83 
84             //////////////////////////////
85             // constructor, saves init, condition and step functors
86             // for later use the parse member function
for_parserboost::spirit::impl::for_parser87             for_parser
88             (
89                 InitF const &i, CondT const &c, StepF const &s,
90                 ParsableT const &p
91             )
92                 : for_init_functor<InitF>(i)
93                 , for_step_functor<StepF>(s)
94                 , eval_t(cond_as_parser_t::convert(c))
95                 , base_t(as_parser_t::convert(p))
96             { }
97 
for_parserboost::spirit::impl::for_parser98             for_parser()
99                 : for_init_functor<InitF>()
100                 , for_step_functor<StepF>()
101                 , eval_t()
102                 , base_t()
103             {}
104 
105             //////////////////////////////
106             // parse member function
107             template <typename ScannerT>
108             typename parser_result<self_t, ScannerT>::type
parseboost::spirit::impl::for_parser109             parse(ScannerT const &scan) const
110             {
111                 typedef typename parser_result<parser_t, ScannerT>::type
112                     body_result_t;
113 
114                 typename ScannerT::iterator_t save(scan.first);
115 
116                 std::size_t length = 0;
117                 std::ptrdiff_t eval_length = 0;
118 
119                 this->init();
120                 while ((eval_length = this->evaluate(scan))>=0)
121                 {
122                     length += eval_length;
123                     body_result_t tmp(this->subject().parse(scan));
124                     if (tmp)
125                     {
126                         length+=tmp.length();
127                     }
128                     else
129                     {
130                         return scan.no_match();
131                     }
132                     this->step();
133                 }
134 
135                 BOOST_SPIRIT_CLASSIC_NS::nil_t attr;
136                 return scan.create_match
137                     (length, attr, save, scan.first);
138             }
139         };
140 
141         //////////////////////////////////
142         // for_parser_gen generates takes the body parser in brackets
143         // and returns the for_parser
144         template <typename InitF, typename CondT, typename StepF>
145         struct for_parser_gen
146         {
for_parser_genboost::spirit::impl::for_parser_gen147             for_parser_gen(InitF const &i, CondT const &c, StepF const &s)
148                 : init(i)
149                 , condition(c)
150                 , step(s)
151             {}
152 
153             template <typename ParsableT>
154             for_parser<InitF, CondT, StepF, ParsableT>
operator []boost::spirit::impl::for_parser_gen155             operator[](ParsableT const &p) const
156             {
157                 return for_parser<InitF, CondT, StepF, ParsableT>
158                     (init, condition, step, p);
159             }
160 
161             InitF const &init;
162             CondT const &condition;
163             StepF const &step;
164         };
165     } // namespace impl
166 
167     //////////////////////////////
168     // for_p, returns for-parser generator
169     // Usage: spirit::for_p(init-ftor, condition, step-ftor)[body]
170     template
171     <
172         typename InitF, typename ConditionT, typename StepF
173     >
174     impl::for_parser_gen<InitF, ConditionT, StepF>
for_p(InitF const & init_f,ConditionT const & condition,StepF const & step_f)175     for_p(InitF const &init_f, ConditionT const &condition, StepF const &step_f)
176     {
177         return impl::for_parser_gen<InitF, ConditionT, StepF>
178             (init_f, condition, step_f);
179     }
180 
181 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
182 
183 }} // namespace BOOST_SPIRIT_CLASSIC_NS
184 
185 #endif // BOOST_SPIRIT_FOR_HPP
186