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 |
|
---|
47 | 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
|
---|
69 | 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 | {
|
---|
107 | 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 | >
|
---|
118 | 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 |
|
---|
153 | 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
|
---|
167 | 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 | {
|
---|
195 | if_parser_gen(CondT const& cond_) : cond(cond_) {}
|
---|
196 |
|
---|
197 | template <typename ParsableT>
|
---|
198 | if_parser
|
---|
199 | <
|
---|
200 | ParsableT,
|
---|
201 | CondT
|
---|
202 | >
|
---|
203 | 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>
|
---|
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
|
---|