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