1 /*=============================================================================
2     Copyright (c) 2002-2003 Joel de Guzman
3     Copyright (c) 2002 Juan Carlos Arevalo-Baeza
4     Copyright (c) 2002-2003 Martin Wille
5     http://spirit.sourceforge.net/
6 
7   Distributed under the Boost Software License, Version 1.0. (See accompanying
8   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #ifndef BOOST_SPIRIT_IF_HPP
11 #define BOOST_SPIRIT_IF_HPP
12 
13 #include <boost/spirit/home/classic/namespace.hpp>
14 #include <boost/spirit/home/classic/core/parser.hpp>
15 #include <boost/spirit/home/classic/core/composite/composite.hpp>
16 #include <boost/spirit/home/classic/dynamic/impl/conditions.ipp>
17 
18 namespace boost { namespace spirit {
19 
20 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
21 
22     namespace impl {
23 
24     //////////////////////////////////
25     // if-else-parser, holds two alternative parsers and a conditional functor
26     // that selects between them.
27     template <typename ParsableTrueT, typename ParsableFalseT, typename CondT>
28     struct if_else_parser
29         : public condition_evaluator<typename as_parser<CondT>::type>
30         , public binary
31         <
32             typename as_parser<ParsableTrueT>::type,
33             typename as_parser<ParsableFalseT>::type,
34             parser< if_else_parser<ParsableTrueT, ParsableFalseT, CondT> >
35         >
36     {
37         typedef if_else_parser<ParsableTrueT, ParsableFalseT, CondT>  self_t;
38 
39         typedef as_parser<ParsableTrueT>            as_parser_true_t;
40         typedef as_parser<ParsableFalseT>           as_parser_false_t;
41         typedef typename as_parser_true_t::type     parser_true_t;
42         typedef typename as_parser_false_t::type    parser_false_t;
43         typedef as_parser<CondT>                    cond_as_parser_t;
44         typedef typename cond_as_parser_t::type     condition_t;
45 
46         typedef binary<parser_true_t, parser_false_t, parser<self_t> > base_t;
47         typedef condition_evaluator<condition_t>                       eval_t;
48 
if_else_parserboost::spirit::impl::if_else_parser49         if_else_parser
50         (
51             ParsableTrueT  const& p_true,
52             ParsableFalseT const& p_false,
53             CondT          const& cond_
54         )
55             : eval_t(cond_as_parser_t::convert(cond_))
56             , base_t
57                 (
58                     as_parser_true_t::convert(p_true),
59                     as_parser_false_t::convert(p_false)
60                 )
61         { }
62 
63         template <typename ScannerT>
64         struct result
65         {
66             typedef typename match_result<ScannerT, nil_t>::type type;
67         };
68 
69         template <typename ScannerT>
70         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::impl::if_else_parser71         parse(ScannerT const& scan) const
72         {
73             typedef typename parser_result
74                 <parser_true_t, ScannerT>::type   then_result_t;
75             typedef typename parser_result
76                 <parser_false_t, ScannerT>::type  else_result_t;
77 
78             typename ScannerT::iterator_t const  save(scan.first);
79 
80             std::ptrdiff_t length = this->evaluate(scan);
81             if (length >= 0)
82             {
83                 then_result_t then_result(this->left().parse(scan));
84                 if (then_result)
85                 {
86                     length += then_result.length();
87                     return scan.create_match(std::size_t(length), nil_t(), save, scan.first);
88                 }
89             }
90             else
91             {
92                 else_result_t else_result(this->right().parse(scan));
93                 if (else_result)
94                 {
95                     length = else_result.length();
96                     return scan.create_match(std::size_t(length), nil_t(), save, scan.first);
97                 }
98             }
99             return scan.no_match();
100         }
101     };
102 
103     //////////////////////////////////
104     // if-else-parser generator, takes the false-parser in brackets
105     // and returns the if-else-parser.
106     template <typename ParsableTrueT, typename CondT>
107     struct if_else_parser_gen
108     {
if_else_parser_genboost::spirit::impl::if_else_parser_gen109         if_else_parser_gen(ParsableTrueT const& p_true_, CondT const& cond_)
110             : p_true(p_true_)
111             , cond(cond_) {}
112 
113         template <typename ParsableFalseT>
114         if_else_parser
115         <
116             ParsableTrueT,
117             ParsableFalseT,
118             CondT
119         >
operator []boost::spirit::impl::if_else_parser_gen120         operator[](ParsableFalseT const& p_false) const
121         {
122             return if_else_parser<ParsableTrueT, ParsableFalseT, CondT>
123                 (
124                     p_true,
125                     p_false,
126                     cond
127                 );
128         }
129 
130         ParsableTrueT const &p_true;
131         CondT const &cond;
132     };
133 
134     //////////////////////////////////
135     // if-parser, conditionally runs a parser is a functor condition is true.
136     // If the condition is false, it fails the parse.
137     // It can optionally become an if-else-parser through the member else_p.
138     template <typename ParsableT, typename CondT>
139     struct if_parser
140         : public condition_evaluator<typename as_parser<CondT>::type>
141         , public unary
142         <
143             typename as_parser<ParsableT>::type,
144             parser<if_parser<ParsableT, CondT> > >
145     {
146         typedef if_parser<ParsableT, CondT>           self_t;
147         typedef as_parser<ParsableT>                  as_parser_t;
148         typedef typename as_parser_t::type            parser_t;
149 
150         typedef as_parser<CondT>                      cond_as_parser_t;
151         typedef typename cond_as_parser_t::type       condition_t;
152         typedef condition_evaluator<condition_t>      eval_t;
153         typedef unary<parser_t, parser<self_t> >      base_t;
154 
if_parserboost::spirit::impl::if_parser155         if_parser(ParsableT const& p, CondT const& cond_)
156             : eval_t(cond_as_parser_t::convert(cond_))
157             , base_t(as_parser_t::convert(p))
158             , else_p(p, cond_)
159         {}
160 
161         template <typename ScannerT>
162         struct result
163         {
164             typedef typename match_result<ScannerT, nil_t>::type type;
165         };
166 
167         template <typename ScannerT>
168         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::impl::if_parser169         parse(ScannerT const& scan) const
170         {
171             typedef typename parser_result<parser_t, ScannerT>::type t_result_t;
172             typename ScannerT::iterator_t const save(scan.first);
173 
174             std::ptrdiff_t length = this->evaluate(scan);
175             if (length >= 0)
176             {
177                 t_result_t then_result(this->subject().parse(scan));
178                 if (then_result)
179                 {
180                     length += then_result.length();
181                     return scan.create_match(std::size_t(length), nil_t(), save, scan.first);
182                 }
183                 return scan.no_match();
184             }
185             return scan.empty_match();
186         }
187 
188         if_else_parser_gen<ParsableT, CondT> else_p;
189     };
190 
191     //////////////////////////////////
192     // if-parser generator, takes the true-parser in brackets and returns the
193     // if-parser.
194     template <typename CondT>
195     struct if_parser_gen
196     {
if_parser_genboost::spirit::impl::if_parser_gen197         if_parser_gen(CondT const& cond_) : cond(cond_) {}
198 
199         template <typename ParsableT>
200         if_parser
201         <
202             ParsableT,
203             CondT
204         >
operator []boost::spirit::impl::if_parser_gen205         operator[](ParsableT const& subject) const
206         {
207             return if_parser<ParsableT, CondT>(subject, cond);
208         }
209 
210         CondT const &cond;
211     };
212 
213 } // namespace impl
214 
215 //////////////////////////////////
216 // if_p function, returns "if" parser generator
217 
218 template <typename CondT>
219 impl::if_parser_gen<CondT>
if_p(CondT const & cond)220 if_p(CondT const& cond)
221 {
222     return impl::if_parser_gen<CondT>(cond);
223 }
224 
225 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
226 
227 }} // namespace BOOST_SPIRIT_CLASSIC_NS
228 
229 #endif // BOOST_SPIRIT_IF_HPP
230