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