~ubuntu-branches/debian/sid/boost1.49/sid

« back to all changes in this revision

Viewing changes to libs/spirit/test/qi/terminal_ex.cpp

  • Committer: Package Import Robot
  • Author(s): Steve M. Robbins
  • Date: 2012-02-26 00:31:44 UTC
  • Revision ID: package-import@ubuntu.com-20120226003144-eaytp12cbf6ubpms
Tags: upstream-1.49.0
ImportĀ upstreamĀ versionĀ 1.49.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*=============================================================================
 
2
    Copyright (c) 2008 Francois Barel
 
3
 
 
4
    Distributed under the Boost Software License, Version 1.0. (See accompanying
 
5
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
6
=============================================================================*/
 
7
#include <boost/detail/lightweight_test.hpp>
 
8
#include <boost/type_traits/is_same.hpp>
 
9
 
 
10
#include <boost/spirit/include/qi_operator.hpp>
 
11
#include <boost/spirit/include/qi_char.hpp>
 
12
#include <boost/spirit/include/phoenix_core.hpp>
 
13
#include <boost/spirit/include/phoenix_operator.hpp>
 
14
 
 
15
#include <iterator>
 
16
#include "test.hpp"
 
17
 
 
18
 
 
19
namespace testns
 
20
{
 
21
 
 
22
    BOOST_SPIRIT_TERMINAL_NAME_EX( ops, ops_type )
 
23
 
 
24
 
 
25
    ///////////////////////////////////////////////////////////////////////////
 
26
    // Parsers
 
27
    ///////////////////////////////////////////////////////////////////////////
 
28
 
 
29
    template <typename T1>
 
30
    struct ops_1_parser
 
31
      : boost::spirit::qi::primitive_parser<ops_1_parser<T1> >
 
32
    {
 
33
        ops_1_parser(T1 t1)
 
34
          : t1(t1)
 
35
        {}
 
36
 
 
37
        template <typename Context, typename Iterator>
 
38
        struct attribute
 
39
        {
 
40
            typedef int type;   // Number of parsed chars.
 
41
        };
 
42
 
 
43
        template <typename Iterator, typename Context
 
44
          , typename Skipper, typename Attribute>
 
45
        bool parse(Iterator& first, Iterator const& last
 
46
          , Context& /*context*/, Skipper const& skipper
 
47
          , Attribute& attr) const
 
48
        {
 
49
            boost::spirit::qi::skip_over(first, last, skipper);
 
50
 
 
51
            int count = 0;
 
52
 
 
53
            Iterator it = first;
 
54
            typedef typename std::iterator_traits<Iterator>::value_type Char;
 
55
            for (T1 t = 0; t < t1; t++, count++)
 
56
                if (it == last || *it++ != Char('+'))
 
57
                    return false;
 
58
 
 
59
            boost::spirit::traits::assign_to(count, attr);
 
60
            first = it;
 
61
            return true;
 
62
        }
 
63
 
 
64
        template <typename Context>
 
65
        boost::spirit::qi::info what(Context& /*context*/) const
 
66
        {
 
67
            return boost::spirit::qi::info("ops_1");
 
68
        }
 
69
 
 
70
        const T1 t1;
 
71
 
 
72
    private:
 
73
        // silence MSVC warning C4512: assignment operator could not be generated
 
74
        ops_1_parser& operator= (ops_1_parser const&);
 
75
    };
 
76
 
 
77
    template <typename T1, typename T2>
 
78
    struct ops_2_parser
 
79
      : boost::spirit::qi::primitive_parser<ops_2_parser<T1, T2> >
 
80
    {
 
81
        ops_2_parser(T1 t1, T2 t2)
 
82
          : t1(t1)
 
83
          , t2(t2)
 
84
        {}
 
85
 
 
86
        template <typename Context, typename Iterator>
 
87
        struct attribute
 
88
        {
 
89
            typedef int type;   // Number of parsed chars.
 
90
        };
 
91
 
 
92
        template <typename Iterator, typename Context
 
93
          , typename Skipper, typename Attribute>
 
94
        bool parse(Iterator& first, Iterator const& last
 
95
          , Context& /*context*/, Skipper const& skipper
 
96
          , Attribute& attr) const
 
97
        {
 
98
            boost::spirit::qi::skip_over(first, last, skipper);
 
99
 
 
100
            int count = 0;
 
101
 
 
102
            Iterator it = first;
 
103
            typedef typename std::iterator_traits<Iterator>::value_type Char;
 
104
            for (T1 t = 0; t < t1; t++, count++)
 
105
                if (it == last || *it++ != Char('+'))
 
106
                    return false;
 
107
            for (T2 t = 0; t < t2; t++, count++)
 
108
                if (it == last || *it++ != Char('-'))
 
109
                    return false;
 
110
 
 
111
            boost::spirit::traits::assign_to(count, attr);
 
112
            first = it;
 
113
            return true;
 
114
        }
 
115
 
 
116
        template <typename Context>
 
117
        boost::spirit::qi::info what(Context& /*context*/) const
 
118
        {
 
119
            return boost::spirit::qi::info("ops_2");
 
120
        }
 
121
 
 
122
        const T1 t1;
 
123
        const T2 t2;
 
124
 
 
125
    private:
 
126
        // silence MSVC warning C4512: assignment operator could not be generated
 
127
        ops_2_parser& operator= (ops_2_parser const&);
 
128
    };
 
129
 
 
130
    template <typename T1, typename T2, typename T3>
 
131
    struct ops_3_parser
 
132
      : boost::spirit::qi::primitive_parser<ops_3_parser<T1, T2, T3> >
 
133
    {
 
134
        ops_3_parser(T1 t1, T2 t2, T3 t3)
 
135
          : t1(t1)
 
136
          , t2(t2)
 
137
          , t3(t3)
 
138
        {}
 
139
 
 
140
        template <typename Context, typename Iterator>
 
141
        struct attribute
 
142
        {
 
143
            typedef int type;   // Number of parsed chars.
 
144
        };
 
145
 
 
146
        template <typename Iterator, typename Context
 
147
          , typename Skipper, typename Attribute>
 
148
        bool parse(Iterator& first, Iterator const& last
 
149
          , Context& /*context*/, Skipper const& skipper
 
150
          , Attribute& attr) const
 
151
        {
 
152
            boost::spirit::qi::skip_over(first, last, skipper);
 
153
 
 
154
            int count = 0;
 
155
 
 
156
            Iterator it = first;
 
157
            typedef typename std::iterator_traits<Iterator>::value_type Char;
 
158
            for (T1 t = 0; t < t1; t++, count++)
 
159
                if (it == last || *it++ != Char('+'))
 
160
                    return false;
 
161
            for (T2 t = 0; t < t2; t++, count++)
 
162
                if (it == last || *it++ != Char('-'))
 
163
                    return false;
 
164
            for (T3 t = 0; t < t3; t++, count++)
 
165
                if (it == last || *it++ != Char('*'))
 
166
                    return false;
 
167
 
 
168
            boost::spirit::traits::assign_to(count, attr);
 
169
            first = it;
 
170
            return true;
 
171
        }
 
172
 
 
173
        template <typename Context>
 
174
        boost::spirit::qi::info what(Context& /*context*/) const
 
175
        {
 
176
            return boost::spirit::qi::info("ops_3");
 
177
        }
 
178
 
 
179
        const T1 t1;
 
180
        const T2 t2;
 
181
        const T3 t3;
 
182
 
 
183
    private:
 
184
        // silence MSVC warning C4512: assignment operator could not be generated
 
185
        ops_3_parser& operator= (ops_3_parser const&);
 
186
    };
 
187
 
 
188
}
 
189
 
 
190
 
 
191
namespace boost { namespace spirit
 
192
{
 
193
 
 
194
    ///////////////////////////////////////////////////////////////////////////
 
195
    // Enablers
 
196
    ///////////////////////////////////////////////////////////////////////////
 
197
 
 
198
    template <typename T1>
 
199
    struct use_terminal<qi::domain
 
200
      , terminal_ex<testns::tag::ops, fusion::vector1<T1> > >
 
201
      : mpl::true_ {};
 
202
 
 
203
    template <typename T1, typename T2>
 
204
    struct use_terminal<qi::domain
 
205
      , terminal_ex<testns::tag::ops, fusion::vector2<T1, T2> > >
 
206
      : mpl::true_ {};
 
207
 
 
208
    template <typename T1, typename T2, typename T3>
 
209
    struct use_terminal<qi::domain
 
210
      , terminal_ex<testns::tag::ops, fusion::vector3<T1, T2, T3> > >
 
211
      : mpl::true_ {};
 
212
 
 
213
    template <>
 
214
    struct use_lazy_terminal<qi::domain, testns::tag::ops, 1>
 
215
      : mpl::true_ {};
 
216
 
 
217
    template <>
 
218
    struct use_lazy_terminal<qi::domain, testns::tag::ops, 2>
 
219
      : mpl::true_ {};
 
220
 
 
221
    template <>
 
222
    struct use_lazy_terminal<qi::domain, testns::tag::ops, 3>
 
223
      : mpl::true_ {};
 
224
 
 
225
}}
 
226
 
 
227
namespace boost { namespace spirit { namespace qi
 
228
{
 
229
 
 
230
    ///////////////////////////////////////////////////////////////////////////
 
231
    // Parser generators: make_xxx function (objects)
 
232
    ///////////////////////////////////////////////////////////////////////////
 
233
 
 
234
    template <typename Modifiers, typename T1>
 
235
    struct make_primitive<
 
236
        terminal_ex<testns::tag::ops, fusion::vector1<T1> >
 
237
      , Modifiers>
 
238
    {
 
239
        typedef testns::ops_1_parser<T1> result_type;
 
240
        template <typename Terminal>
 
241
        result_type operator()(const Terminal& term, unused_type) const
 
242
        {
 
243
            return result_type(
 
244
                fusion::at_c<0>(term.args)
 
245
            );
 
246
        }
 
247
    };
 
248
 
 
249
    template <typename Modifiers, typename T1, typename T2>
 
250
    struct make_primitive<
 
251
        terminal_ex<testns::tag::ops, fusion::vector2<T1, T2> >
 
252
      , Modifiers>
 
253
    {
 
254
        typedef testns::ops_2_parser<T1, T2> result_type;
 
255
        template <typename Terminal>
 
256
        result_type operator()(const Terminal& term, unused_type) const
 
257
        {
 
258
            return result_type(
 
259
                fusion::at_c<0>(term.args)
 
260
              , fusion::at_c<1>(term.args)
 
261
            );
 
262
        }
 
263
    };
 
264
 
 
265
    template <typename Modifiers, typename T1, typename T2, typename T3>
 
266
    struct make_primitive<
 
267
        terminal_ex<testns::tag::ops, fusion::vector3<T1, T2, T3> >
 
268
      , Modifiers>
 
269
    {
 
270
        typedef testns::ops_3_parser<T1, T2, T3> result_type;
 
271
        template <typename Terminal>
 
272
        result_type operator()(const Terminal& term, unused_type) const
 
273
        {
 
274
            return result_type(
 
275
                fusion::at_c<0>(term.args)
 
276
              , fusion::at_c<1>(term.args)
 
277
              , fusion::at_c<2>(term.args)
 
278
            );
 
279
        }
 
280
    };
 
281
 
 
282
}}}
 
283
 
 
284
 
 
285
namespace testns
 
286
{
 
287
    template <typename T1, typename T>
 
288
    void check_type_1(const T& /*t*/)
 
289
    {
 
290
        namespace fusion = boost::fusion;
 
291
        BOOST_STATIC_ASSERT(( boost::is_same<T
 
292
          , typename boost::spirit::terminal<testns::tag::ops>::result<T1>::type >::value ));
 
293
    }
 
294
 
 
295
    template <typename T1, typename T2, typename T>
 
296
    void check_type_2(const T& /*t*/)
 
297
    {
 
298
        namespace fusion = boost::fusion;
 
299
        BOOST_STATIC_ASSERT(( boost::is_same<T
 
300
          , typename boost::spirit::terminal<testns::tag::ops>::result<T1, T2>::type >::value ));
 
301
    }
 
302
 
 
303
    template <typename T1, typename T2, typename T3, typename T>
 
304
    void check_type_3(const T& /*t*/)
 
305
    {
 
306
        namespace fusion = boost::fusion;
 
307
        BOOST_STATIC_ASSERT(( boost::is_same<T
 
308
          , typename boost::spirit::terminal<testns::tag::ops>::result<T1, T2, T3>::type >::value ));
 
309
    }
 
310
}
 
311
 
 
312
 
 
313
int
 
314
main()
 
315
{
 
316
    using spirit_test::test_attr;
 
317
    using spirit_test::test;
 
318
 
 
319
    using testns::ops;
 
320
    using testns::check_type_1;
 
321
    using testns::check_type_2;
 
322
    using testns::check_type_3;
 
323
 
 
324
    { // immediate args
 
325
        int c = 0;
 
326
#define IP1 ops(2)
 
327
        check_type_1<int>(IP1);
 
328
        BOOST_TEST(test_attr("++/", IP1 >> '/', c) && c == 2);
 
329
 
 
330
        c = 0;
 
331
#define IP2 ops(2, 3)
 
332
        check_type_2<int, int>(IP2);
 
333
        BOOST_TEST(test_attr("++---/", IP2 >> '/', c) && c == 5);
 
334
 
 
335
        c = 0;
 
336
#define IP3 ops(2, 3, 4)
 
337
        check_type_3<int, int, int>(IP3);
 
338
        BOOST_TEST(!test("++---***/", IP3 >> '/'));
 
339
#define IP4 ops(2, 3, 4)
 
340
        check_type_3<int, int, int>(IP4);
 
341
        BOOST_TEST(test_attr("++---****/", IP4 >> '/', c) && c == 9);
 
342
    }
 
343
 
 
344
#ifndef BOOST_SPIRIT_USE_PHOENIX_V3
 
345
 
 
346
    using boost::phoenix::val;
 
347
    using boost::phoenix::actor;
 
348
    using boost::phoenix::value;
 
349
 
 
350
    { // all lazy args
 
351
        int c = 0;
 
352
#define LP1 ops(val(1))
 
353
        check_type_1<actor<value<int> > >(LP1);
 
354
        BOOST_TEST(test_attr("+/", LP1 >> '/', c) && c == 1);
 
355
 
 
356
        c = 0;
 
357
#define LP2 ops(val(1), val(4))
 
358
        check_type_2<actor<value<int> >, actor<value<int> > >(LP2);
 
359
        BOOST_TEST(test_attr("+----/", LP2 >> '/', c) && c == 5);
 
360
 
 
361
        c = 0;
 
362
#define LP3 ops(val((char)2), val(3.), val(4))
 
363
        check_type_3<actor<value<char> >, actor<value<double> >, actor<value<int> > >(LP3);
 
364
        BOOST_TEST(!test("++---***/", LP3 >> '/'));
 
365
#define LP4 ops(val(1), val(2), val(3))
 
366
        check_type_3<actor<value<int> >, actor<value<int> >, actor<value<int> > >(LP4);
 
367
        BOOST_TEST(test_attr("+--***/", LP4 >> '/', c) && c == 6);
 
368
    }
 
369
 
 
370
    { // mixed immediate and lazy args
 
371
        namespace fusion = boost::fusion;
 
372
        namespace phx = boost::phoenix;
 
373
 
 
374
        int c = 0;
 
375
#define MP1 ops(val(3), 2)
 
376
        check_type_2<actor<value<int> >, int>(MP1);
 
377
        BOOST_TEST(test_attr("+++--/", MP1 >> '/', c) && c == 5);
 
378
 
 
379
        c = 0;
 
380
#define MP2 ops(4, val(1))
 
381
        check_type_2<int, actor<value<int> > >(MP2);
 
382
        BOOST_TEST(test_attr("++++-/", MP2 >> '/', c) && c == 5);
 
383
 
 
384
        c = 0;
 
385
#define MP3 ops(2, val(2), val(2))
 
386
        check_type_3<int, actor<value<int> >, actor<value<int> > >(MP3);
 
387
        BOOST_TEST(!test("++-**/", MP3 >> '/'));
 
388
#define MP4 ops(2, val(2), 2)
 
389
        check_type_3<int, actor<value<int> >, int>(MP4);
 
390
        BOOST_TEST(test_attr("++--**/", MP4 >> '/', c) && c == 6);
 
391
 
 
392
        c = 0;
 
393
#define MP5 ops(val(5) - val(3), 2, val(2))
 
394
        check_type_3<actor<phx::composite<phx::minus_eval, fusion::vector<value<int>, value<int> > > >, int, actor<value<int> > >(MP5);
 
395
        BOOST_TEST(test_attr("++--**/", MP5 >> '/', c) && c == 6);
 
396
    }
 
397
 
 
398
#else // BOOST_SPIRIT_USE_PHOENIX_V3
 
399
 
 
400
    using boost::phoenix::val;
 
401
    using boost::phoenix::actor;
 
402
    using boost::phoenix::expression::value;
 
403
 
 
404
    { // all lazy args
 
405
        int c = 0;
 
406
#define LP1 ops(val(1))
 
407
        check_type_1<value<int>::type>(LP1);
 
408
        BOOST_TEST(test_attr("+/", LP1 >> '/', c) && c == 1);
 
409
 
 
410
        c = 0;
 
411
#define LP2 ops(val(1), val(4))
 
412
        check_type_2<value<int>::type, value<int>::type>(LP2);
 
413
        BOOST_TEST(test_attr("+----/", LP2 >> '/', c) && c == 5);
 
414
 
 
415
        c = 0;
 
416
#define LP3 ops(val((char)2), val(3.), val(4))
 
417
        check_type_3<value<char>::type, value<double>::type, value<int>::type>(LP3);
 
418
        BOOST_TEST(!test("++---***/", LP3 >> '/'));
 
419
#define LP4 ops(val(1), val(2), val(3))
 
420
        check_type_3<value<int>::type, value<int>::type, value<int>::type>(LP4);
 
421
        BOOST_TEST(test_attr("+--***/", LP4 >> '/', c) && c == 6);
 
422
    }
 
423
 
 
424
    { // mixed immediate and lazy args
 
425
        namespace fusion = boost::fusion;
 
426
        namespace phx = boost::phoenix;
 
427
 
 
428
        int c = 0;
 
429
#define MP1 ops(val(3), 2)
 
430
        check_type_2<value<int>::type, int>(MP1);
 
431
        BOOST_TEST(test_attr("+++--/", MP1 >> '/', c) && c == 5);
 
432
 
 
433
        c = 0;
 
434
#define MP2 ops(4, val(1))
 
435
        check_type_2<int, value<int>::type>(MP2);
 
436
        BOOST_TEST(test_attr("++++-/", MP2 >> '/', c) && c == 5);
 
437
 
 
438
        c = 0;
 
439
#define MP3 ops(2, val(2), val(2))
 
440
        check_type_3<int, value<int>::type, value<int>::type>(MP3);
 
441
        BOOST_TEST(!test("++-**/", MP3 >> '/'));
 
442
#define MP4 ops(2, val(2), 2)
 
443
        check_type_3<int, value<int>::type, int>(MP4);
 
444
        BOOST_TEST(test_attr("++--**/", MP4 >> '/', c) && c == 6);
 
445
 
 
446
        c = 0;
 
447
#define MP5 ops(val(5) - val(3), 2, val(2))
 
448
        check_type_3<phx::expression::minus<value<int>::type, value<int>::type>::type, int, value<int>::type>(MP5);
 
449
        BOOST_TEST(test_attr("++--**/", MP5 >> '/', c) && c == 6);
 
450
    }
 
451
#endif
 
452
 
 
453
    return boost::report_errors();
 
454
}
 
455