1 /*=============================================================================
2     Copyright (c) 1998-2003 Joel de Guzman
3     Copyright (c) 2001 Daniel Nuffer
4     Copyright (c) 2002 Hartmut Kaiser
5     http://spirit.sourceforge.net/
6 
7   Distributed under the Boost Software License, Version 1.0. (See accompanying
8   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #if !defined(BOOST_SPIRIT_POSITIVE_HPP)
11 #define BOOST_SPIRIT_POSITIVE_HPP
12 
13 #include <boost/spirit/home/classic/namespace.hpp>
14 #include <boost/spirit/home/classic/core/parser.hpp>
15 #include <boost/spirit/home/classic/core/primitives/primitives.hpp>
16 #include <boost/spirit/home/classic/core/composite/composite.hpp>
17 #include <boost/spirit/home/classic/meta/as_parser.hpp>
18 
19 namespace boost { namespace spirit {
20 
21 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
22 
23     ///////////////////////////////////////////////////////////////////////////
24     //
25     //  positive class
26     //
27     //      Handles expressions of the form:
28     //
29     //          +a
30     //
31     //      where a is a parser. The expression returns a composite
32     //      parser that matches its subject one (1) or more times.
33     //
34     ///////////////////////////////////////////////////////////////////////////
35     struct positive_parser_gen;
36 
37 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
38 #pragma warning(push)
39 #pragma warning(disable:4512) //assignment operator could not be generated
40 #endif
41 
42     template <typename S>
43     struct positive
44     :   public unary<S, parser<positive<S> > >
45     {
46         typedef positive<S>                 self_t;
47         typedef unary_parser_category       parser_category_t;
48         typedef positive_parser_gen         parser_generator_t;
49         typedef unary<S, parser<self_t> >   base_t;
50 
positiveboost::spirit::positive51         positive(S const& a)
52         : base_t(a) {}
53 
54         template <typename ScannerT>
55         typename parser_result<self_t, ScannerT>::type
parseboost::spirit::positive56         parse(ScannerT const& scan) const
57         {
58             typedef typename parser_result<self_t, ScannerT>::type result_t;
59             typedef typename ScannerT::iterator_t iterator_t;
60             result_t hit = this->subject().parse(scan);
61 
62             if (hit)
63             {
64                 for (;;)
65                 {
66                     iterator_t save = scan.first;
67                     if (result_t next = this->subject().parse(scan))
68                     {
69                         scan.concat_match(hit, next);
70                     }
71                     else
72                     {
73                         scan.first = save;
74                         break;
75                     }
76                 }
77             }
78             return hit;
79         }
80     };
81 
82 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
83 #pragma warning(pop)
84 #endif
85 
86     struct positive_parser_gen
87     {
88         template <typename S>
89         struct result
90         {
91             typedef positive<S> type;
92         };
93 
94         template <typename S>
95         static positive<S>
generateboost::spirit::positive_parser_gen96         generate(parser<S> const& a)
97         {
98             return positive<S>(a.derived());
99         }
100     };
101 
102     template <typename S>
103     inline positive<S>
104     operator+(parser<S> const& a);
105 
106 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
107 
108 }} // namespace BOOST_SPIRIT_CLASSIC_NS
109 
110 #endif
111 
112 #include <boost/spirit/home/classic/core/composite/impl/positive.ipp>
113