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