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 ////////////////////////////////////////////////////////////////////////////////
20 namespace boost { namespace spirit {
21 
22 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
23 
24 ///////////////////////////////////////////////////////////////////////////////
25 //
26 //  condition_parser class
27 //
28 //      handles expresions of the form
29 //
30 //          epsilon_p(cond)
31 //
32 //      where cond is a function or a functor that returns a value suitable
33 //      to be used in boolean context. The expression returns a parser that
34 //      returns an empty match when the condition evaluates to true.
35 //
36 ///////////////////////////////////////////////////////////////////////////////
37     template <typename CondT, bool positive_ = true>
38     struct condition_parser : parser<condition_parser<CondT, positive_> >
39     {
40         typedef condition_parser<CondT, positive_> self_t;
41 
42         // not explicit! (needed for implementation of if_p et al.)
condition_parserboost::spirit::condition_parser43         condition_parser(CondT const& cond_) : cond(cond_) {}
44 
45         template <typename ScannerT>
46         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::condition_parser47         parse(ScannerT const& scan) const
48         {
49             if (positive_ == bool(cond())) // allow cond to return int
50                 return scan.empty_match();
51             else
52                 return scan.no_match();
53         }
54 
55         condition_parser<CondT, !positive_>
negateboost::spirit::condition_parser56         negate() const
57         { return condition_parser<CondT, !positive_>(cond); }
58 
59     private:
60 
61         CondT cond;
62     };
63 
64 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) || \
65     BOOST_WORKAROUND(BOOST_MSVC, == 1400) || \
66     BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
67 // VC 7.1, VC8 and Sun CC <= 5.8 do not support general
68 // expressions of non-type template parameters in instantiations
69     template <typename CondT>
70     inline condition_parser<CondT, false>
operator ~(condition_parser<CondT,true> const & p)71     operator~(condition_parser<CondT, true> const& p)
72     { return p.negate(); }
73 
74     template <typename CondT>
75     inline condition_parser<CondT, true>
operator ~(condition_parser<CondT,false> const & p)76     operator~(condition_parser<CondT, false> const& p)
77     { return p.negate(); }
78 #else // BOOST_WORKAROUND(BOOST_MSVC, == 1310) || == 1400
79     template <typename CondT, bool positive>
80     inline condition_parser<CondT, !positive>
operator ~(condition_parser<CondT,positive> const & p)81     operator~(condition_parser<CondT, positive> const& p)
82     { return p.negate(); }
83 #endif // BOOST_WORKAROUND(BOOST_MSVC, == 1310) || == 1400
84 
85 ///////////////////////////////////////////////////////////////////////////////
86 //
87 //  empty_match_parser class
88 //
89 //      handles expressions of the form
90 //          epsilon_p(subject)
91 //      where subject is a parser. The expresion returns a composite
92 //      parser that returns an empty match if the subject parser matches.
93 //
94 ///////////////////////////////////////////////////////////////////////////////
95     struct empty_match_parser_gen;
96     struct negated_empty_match_parser_gen;
97 
98     template <typename SubjectT>
99     struct negated_empty_match_parser; // Forward declaration
100 
101     template<typename SubjectT>
102     struct empty_match_parser
103     : unary<SubjectT, parser<empty_match_parser<SubjectT> > >
104     {
105         typedef empty_match_parser<SubjectT>        self_t;
106         typedef unary<SubjectT, parser<self_t> >    base_t;
107         typedef unary_parser_category               parser_category_t;
108         typedef empty_match_parser_gen              parser_genererator_t;
109         typedef self_t embed_t;
110 
empty_match_parserboost::spirit::empty_match_parser111         explicit empty_match_parser(SubjectT const& p) : base_t(p) {}
112 
113         template <typename ScannerT>
114         struct result
115         { typedef typename match_result<ScannerT, nil_t>::type type; };
116 
117         template <typename ScannerT>
118         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::empty_match_parser119         parse(ScannerT const& scan) const
120         {
121             typename ScannerT::iterator_t save(scan.first);
122 
123             typedef typename no_actions_scanner<ScannerT>::policies_t
124                 policies_t;
125 
126             bool matches = this->subject().parse(
127                 scan.change_policies(policies_t(scan)));
128             if (matches)
129             {
130                 scan.first = save; // reset the position
131                 return scan.empty_match();
132             }
133             else
134             {
135                 return scan.no_match();
136             }
137         }
138 
139         negated_empty_match_parser<SubjectT>
negateboost::spirit::empty_match_parser140         negate() const
141         { return negated_empty_match_parser<SubjectT>(this->subject()); }
142     };
143 
144     template<typename SubjectT>
145     struct negated_empty_match_parser
146     : public unary<SubjectT, parser<negated_empty_match_parser<SubjectT> > >
147     {
148         typedef negated_empty_match_parser<SubjectT>    self_t;
149         typedef unary<SubjectT, parser<self_t> >        base_t;
150         typedef unary_parser_category                   parser_category_t;
151         typedef negated_empty_match_parser_gen          parser_genererator_t;
152 
negated_empty_match_parserboost::spirit::negated_empty_match_parser153         explicit negated_empty_match_parser(SubjectT const& p) : base_t(p) {}
154 
155         template <typename ScannerT>
156         struct result
157         { typedef typename match_result<ScannerT, nil_t>::type type; };
158 
159         template <typename ScannerT>
160         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::negated_empty_match_parser161         parse(ScannerT const& scan) const
162         {
163             typename ScannerT::iterator_t save(scan.first);
164 
165             typedef typename no_actions_scanner<ScannerT>::policies_t
166                 policies_t;
167 
168             bool matches = this->subject().parse(
169                 scan.change_policies(policies_t(scan)));
170             if (!matches)
171             {
172                 scan.first = save; // reset the position
173                 return scan.empty_match();
174             }
175             else
176             {
177                 return scan.no_match();
178             }
179         }
180 
181         empty_match_parser<SubjectT>
negateboost::spirit::negated_empty_match_parser182         negate() const
183         { return empty_match_parser<SubjectT>(this->subject()); }
184     };
185 
186     struct empty_match_parser_gen
187     {
188         template <typename SubjectT>
189         struct result
190         { typedef empty_match_parser<SubjectT> type; };
191 
192         template <typename SubjectT>
193         static empty_match_parser<SubjectT>
generateboost::spirit::empty_match_parser_gen194         generate(parser<SubjectT> const& subject)
195         { return empty_match_parser<SubjectT>(subject.derived()); }
196     };
197 
198     struct negated_empty_match_parser_gen
199     {
200         template <typename SubjectT>
201         struct result
202         { typedef negated_empty_match_parser<SubjectT> type; };
203 
204         template <typename SubjectT>
205         static negated_empty_match_parser<SubjectT>
generateboost::spirit::negated_empty_match_parser_gen206         generate(parser<SubjectT> const& subject)
207         { return negated_empty_match_parser<SubjectT>(subject.derived()); }
208     };
209 
210     //////////////////////////////
211     template <typename SubjectT>
212     inline negated_empty_match_parser<SubjectT>
operator ~(empty_match_parser<SubjectT> const & p)213     operator~(empty_match_parser<SubjectT> const& p)
214     { return p.negate(); }
215 
216     template <typename SubjectT>
217     inline empty_match_parser<SubjectT>
operator ~(negated_empty_match_parser<SubjectT> const & p)218     operator~(negated_empty_match_parser<SubjectT> const& p)
219     { return p.negate(); }
220 
221 ///////////////////////////////////////////////////////////////////////////////
222 //
223 //  epsilon_ parser and parser generator class
224 //
225 //      Operates as primitive parser that always matches an empty sequence.
226 //
227 //      Also operates as a parser generator. According to the type of the
228 //      argument an instance of empty_match_parser<> (when the argument is
229 //      a parser) or condition_parser<> (when the argument is not a parser)
230 //      is returned by operator().
231 //
232 ///////////////////////////////////////////////////////////////////////////////
233     namespace impl
234     {
235         template <typename SubjectT>
236         struct epsilon_selector
237         {
238             typedef typename as_parser<SubjectT>::type subject_t;
239             typedef typename
240                 mpl::if_<
241                     is_parser<subject_t>
242                     ,empty_match_parser<subject_t>
243                     ,condition_parser<subject_t>
244                 >::type type;
245         };
246     }
247 
248     struct epsilon_parser : public parser<epsilon_parser>
249     {
250         typedef epsilon_parser self_t;
251 
epsilon_parserboost::spirit::epsilon_parser252         epsilon_parser() {}
253 
254         template <typename ScannerT>
255         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::epsilon_parser256         parse(ScannerT const& scan) const
257         { return scan.empty_match(); }
258 
259         template <typename SubjectT>
260         typename impl::epsilon_selector<SubjectT>::type
operator ()boost::spirit::epsilon_parser261         operator()(SubjectT const& subject) const
262         {
263             typedef typename impl::epsilon_selector<SubjectT>::type result_t;
264             return result_t(subject);
265         }
266     };
267 
268     epsilon_parser const epsilon_p = epsilon_parser();
269     epsilon_parser const eps_p = epsilon_parser();
270 
271 ///////////////////////////////////////////////////////////////////////////////
272 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
273 
274 }} // namespace BOOST_SPIRIT_CLASSIC_NS
275 
276 #endif
277