1 /*=============================================================================
2     Copyright (c) 1998-2003 Joel de Guzman
3     Copyright (c) 2002-2003 Martin Wille
4     http://spirit.sourceforge.net/
5 
6   Distributed under the Boost Software License, Version 1.0. (See accompanying
7   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #ifndef BOOST_SPIRIT_EPSILON_HPP
10 #define BOOST_SPIRIT_EPSILON_HPP
11 
12 ////////////////////////////////////////////////////////////////////////////////
13 #include <boost/spirit/home/classic/namespace.hpp>
14 #include <boost/spirit/home/classic/core/parser.hpp>
15 #include <boost/spirit/home/classic/meta/parser_traits.hpp>
16 #include <boost/spirit/home/classic/core/composite/composite.hpp>
17 #include <boost/spirit/home/classic/core/composite/no_actions.hpp>
18 
19 #if defined(BOOST_MSVC)
20 # pragma warning(push)
21 # pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
22 #endif
23 
24 ////////////////////////////////////////////////////////////////////////////////
25 namespace boost { namespace spirit {
26 
27 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 //
31 //  condition_parser class
32 //
33 //      handles expresions of the form
34 //
35 //          epsilon_p(cond)
36 //
37 //      where cond is a function or a functor that returns a value suitable
38 //      to be used in boolean context. The expression returns a parser that
39 //      returns an empty match when the condition evaluates to true.
40 //
41 ///////////////////////////////////////////////////////////////////////////////
42     template <typename CondT, bool positive_ = true>
43     struct condition_parser : parser<condition_parser<CondT, positive_> >
44     {
45         typedef condition_parser<CondT, positive_> self_t;
46 
47         // not explicit! (needed for implementation of if_p et al.)
condition_parserboost::spirit::condition_parser48         condition_parser(CondT const& cond_) : cond(cond_) {}
49 
50         template <typename ScannerT>
51         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::condition_parser52         parse(ScannerT const& scan) const
53         {
54             if (positive_ == bool(cond())) // allow cond to return int
55                 return scan.empty_match();
56             else
57                 return scan.no_match();
58         }
59 
60         condition_parser<CondT, !positive_>
negateboost::spirit::condition_parser61         negate() const
62         { return condition_parser<CondT, !positive_>(cond); }
63 
64     private:
65 
66         CondT cond;
67     };
68 
69 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) || \
70     BOOST_WORKAROUND(BOOST_MSVC, == 1400) || \
71     BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
72 // VC 7.1, VC8 and Sun CC <= 5.8 do not support general
73 // expressions of non-type template parameters in instantiations
74     template <typename CondT>
75     inline condition_parser<CondT, false>
operator ~(condition_parser<CondT,true> const & p)76     operator~(condition_parser<CondT, true> const& p)
77     { return p.negate(); }
78 
79     template <typename CondT>
80     inline condition_parser<CondT, true>
operator ~(condition_parser<CondT,false> const & p)81     operator~(condition_parser<CondT, false> const& p)
82     { return p.negate(); }
83 #else // BOOST_WORKAROUND(BOOST_MSVC, == 1310) || == 1400
84     template <typename CondT, bool positive>
85     inline condition_parser<CondT, !positive>
operator ~(condition_parser<CondT,positive> const & p)86     operator~(condition_parser<CondT, positive> const& p)
87     { return p.negate(); }
88 #endif // BOOST_WORKAROUND(BOOST_MSVC, == 1310) || == 1400
89 
90 ///////////////////////////////////////////////////////////////////////////////
91 //
92 //  empty_match_parser class
93 //
94 //      handles expressions of the form
95 //          epsilon_p(subject)
96 //      where subject is a parser. The expresion returns a composite
97 //      parser that returns an empty match if the subject parser matches.
98 //
99 ///////////////////////////////////////////////////////////////////////////////
100     struct empty_match_parser_gen;
101     struct negated_empty_match_parser_gen;
102 
103     template <typename SubjectT>
104     struct negated_empty_match_parser; // Forward declaration
105 
106     template<typename SubjectT>
107     struct empty_match_parser
108     : unary<SubjectT, parser<empty_match_parser<SubjectT> > >
109     {
110         typedef empty_match_parser<SubjectT>        self_t;
111         typedef unary<SubjectT, parser<self_t> >    base_t;
112         typedef unary_parser_category               parser_category_t;
113         typedef empty_match_parser_gen              parser_genererator_t;
114         typedef self_t embed_t;
115 
empty_match_parserboost::spirit::empty_match_parser116         explicit empty_match_parser(SubjectT const& p) : base_t(p) {}
117 
118         template <typename ScannerT>
119         struct result
120         { typedef typename match_result<ScannerT, nil_t>::type type; };
121 
122         template <typename ScannerT>
123         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::empty_match_parser124         parse(ScannerT const& scan) const
125         {
126             typename ScannerT::iterator_t save(scan.first);
127 
128             typedef typename no_actions_scanner<ScannerT>::policies_t
129                 policies_t;
130 
131             bool matches = this->subject().parse(
132                 scan.change_policies(policies_t(scan)));
133             if (matches)
134             {
135                 scan.first = save; // reset the position
136                 return scan.empty_match();
137             }
138             else
139             {
140                 return scan.no_match();
141             }
142         }
143 
144         negated_empty_match_parser<SubjectT>
negateboost::spirit::empty_match_parser145         negate() const
146         { return negated_empty_match_parser<SubjectT>(this->subject()); }
147     };
148 
149     template<typename SubjectT>
150     struct negated_empty_match_parser
151     : public unary<SubjectT, parser<negated_empty_match_parser<SubjectT> > >
152     {
153         typedef negated_empty_match_parser<SubjectT>    self_t;
154         typedef unary<SubjectT, parser<self_t> >        base_t;
155         typedef unary_parser_category                   parser_category_t;
156         typedef negated_empty_match_parser_gen          parser_genererator_t;
157 
negated_empty_match_parserboost::spirit::negated_empty_match_parser158         explicit negated_empty_match_parser(SubjectT const& p) : base_t(p) {}
159 
160         template <typename ScannerT>
161         struct result
162         { typedef typename match_result<ScannerT, nil_t>::type type; };
163 
164         template <typename ScannerT>
165         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::negated_empty_match_parser166         parse(ScannerT const& scan) const
167         {
168             typename ScannerT::iterator_t save(scan.first);
169 
170             typedef typename no_actions_scanner<ScannerT>::policies_t
171                 policies_t;
172 
173             bool matches = this->subject().parse(
174                 scan.change_policies(policies_t(scan)));
175             if (!matches)
176             {
177                 scan.first = save; // reset the position
178                 return scan.empty_match();
179             }
180             else
181             {
182                 return scan.no_match();
183             }
184         }
185 
186         empty_match_parser<SubjectT>
negateboost::spirit::negated_empty_match_parser187         negate() const
188         { return empty_match_parser<SubjectT>(this->subject()); }
189     };
190 
191     struct empty_match_parser_gen
192     {
193         template <typename SubjectT>
194         struct result
195         { typedef empty_match_parser<SubjectT> type; };
196 
197         template <typename SubjectT>
198         static empty_match_parser<SubjectT>
generateboost::spirit::empty_match_parser_gen199         generate(parser<SubjectT> const& subject)
200         { return empty_match_parser<SubjectT>(subject.derived()); }
201     };
202 
203     struct negated_empty_match_parser_gen
204     {
205         template <typename SubjectT>
206         struct result
207         { typedef negated_empty_match_parser<SubjectT> type; };
208 
209         template <typename SubjectT>
210         static negated_empty_match_parser<SubjectT>
generateboost::spirit::negated_empty_match_parser_gen211         generate(parser<SubjectT> const& subject)
212         { return negated_empty_match_parser<SubjectT>(subject.derived()); }
213     };
214 
215     //////////////////////////////
216     template <typename SubjectT>
217     inline negated_empty_match_parser<SubjectT>
operator ~(empty_match_parser<SubjectT> const & p)218     operator~(empty_match_parser<SubjectT> const& p)
219     { return p.negate(); }
220 
221     template <typename SubjectT>
222     inline empty_match_parser<SubjectT>
operator ~(negated_empty_match_parser<SubjectT> const & p)223     operator~(negated_empty_match_parser<SubjectT> const& p)
224     { return p.negate(); }
225 
226 ///////////////////////////////////////////////////////////////////////////////
227 //
228 //  epsilon_ parser and parser generator class
229 //
230 //      Operates as primitive parser that always matches an empty sequence.
231 //
232 //      Also operates as a parser generator. According to the type of the
233 //      argument an instance of empty_match_parser<> (when the argument is
234 //      a parser) or condition_parser<> (when the argument is not a parser)
235 //      is returned by operator().
236 //
237 ///////////////////////////////////////////////////////////////////////////////
238     namespace impl
239     {
240         template <typename SubjectT>
241         struct epsilon_selector
242         {
243             typedef typename as_parser<SubjectT>::type subject_t;
244             typedef typename
245                 mpl::if_<
246                     is_parser<subject_t>
247                     ,empty_match_parser<subject_t>
248                     ,condition_parser<subject_t>
249                 >::type type;
250         };
251     }
252 
253     struct epsilon_parser : public parser<epsilon_parser>
254     {
255         typedef epsilon_parser self_t;
256 
epsilon_parserboost::spirit::epsilon_parser257         epsilon_parser() {}
258 
259         template <typename ScannerT>
260         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::epsilon_parser261         parse(ScannerT const& scan) const
262         { return scan.empty_match(); }
263 
264         template <typename SubjectT>
265         typename impl::epsilon_selector<SubjectT>::type
operator ()boost::spirit::epsilon_parser266         operator()(SubjectT const& subject) const
267         {
268             typedef typename impl::epsilon_selector<SubjectT>::type result_t;
269             return result_t(subject);
270         }
271     };
272 
273     epsilon_parser const epsilon_p = epsilon_parser();
274     epsilon_parser const eps_p = epsilon_parser();
275 
276 ///////////////////////////////////////////////////////////////////////////////
277 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
278 
279 }} // namespace BOOST_SPIRIT_CLASSIC_NS
280 
281 #ifdef BOOST_MSVC
282 # pragma warning (pop)
283 #endif
284 
285 #endif
286