source: NonGTP/Boost/boost/spirit/dynamic/if.hpp @ 857

Revision 857, 7.7 KB checked in by igarcia, 18 years ago (diff)
Line 
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
18namespace 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
216template <typename CondT>
217impl::if_parser_gen<CondT>
218if_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
Note: See TracBrowser for help on using the repository browser.