]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
49 | 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 | |
71 | 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 | { | |
109 | 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 | > | |
120 | 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 fales, 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 | ||
155 | 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 | |
169 | 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 | { | |
197 | if_parser_gen(CondT const& cond_) : cond(cond_) {} | |
198 | ||
199 | template <typename ParsableT> | |
200 | if_parser | |
201 | < | |
202 | ParsableT, | |
203 | CondT | |
204 | > | |
205 | 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> | |
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 |