1 /*=============================================================================
2     Copyright (c) 2001-2011 Hartmut Kaiser
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 #if !defined(BOOST_SPIRIT_MATCH_MANIP_MAY_05_2007_1203PM)
8 #define BOOST_SPIRIT_MATCH_MANIP_MAY_05_2007_1203PM
9 
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13 
14 #include <boost/spirit/home/qi/parse.hpp>
15 #include <boost/spirit/home/support/iterators/istream_iterator.hpp>
16 #include <boost/spirit/home/support/unused.hpp>
17 #include <boost/mpl/bool.hpp>
18 
19 #include <iterator>
20 #include <string>
21 
22 ///////////////////////////////////////////////////////////////////////////////
23 namespace boost { namespace spirit { namespace qi { namespace detail
24 {
25     ///////////////////////////////////////////////////////////////////////////
26     template <typename Expr
27       , typename CopyExpr = mpl::false_, typename CopyAttr = mpl::false_
28       , typename Skipper = unused_type, typename Attribute = unused_type const>
29     struct match_manip
30     {
31         // This assertion makes sure we don't hit the only code path which is
32         // not implemented (because it isn't needed), where both, the
33         // expression and the attribute need to be held as a copy.
34         BOOST_SPIRIT_ASSERT_MSG(!CopyExpr::value || !CopyAttr::value
35             , error_invalid_should_not_happen, ());
36 
match_manipboost::spirit::qi::detail::match_manip37         match_manip(Expr const& xpr, Skipper const& s, Attribute& a)
38           : expr(xpr), skipper(s), attr(a), post_skip(skip_flag::postskip) {}
39 
match_manipboost::spirit::qi::detail::match_manip40         match_manip(Expr const& xpr, Skipper const& s
41             , BOOST_SCOPED_ENUM(skip_flag) ps, Attribute& a)
42           : expr(xpr), skipper(s), attr(a), post_skip(ps) {}
43 
44         Expr const& expr;
45         Skipper const& skipper;
46         Attribute& attr;
47         BOOST_SCOPED_ENUM(skip_flag) const post_skip;
48 
49         // silence MSVC warning C4512: assignment operator could not be generated
50         BOOST_DELETED_FUNCTION(match_manip& operator= (match_manip const&))
51     };
52 
53     template <typename Expr, typename Skipper, typename Attribute>
54     struct match_manip<Expr, mpl::false_, mpl::true_, Skipper, Attribute>
55     {
match_manipboost::spirit::qi::detail::match_manip56         match_manip(Expr const& xpr, Skipper const& s, Attribute& a)
57           : expr(xpr), skipper(s), attr(a), post_skip(skip_flag::postskip) {}
58 
match_manipboost::spirit::qi::detail::match_manip59         match_manip(Expr const& xpr, Skipper const& s
60             , BOOST_SCOPED_ENUM(skip_flag) ps, Attribute& a)
61           : expr(xpr), skipper(s), attr(a), post_skip(ps) {}
62 
63         Expr const& expr;
64         Skipper const& skipper;
65         Attribute attr;
66         BOOST_SCOPED_ENUM(skip_flag) const post_skip;
67 
68         // silence MSVC warning C4512: assignment operator could not be generated
69         BOOST_DELETED_FUNCTION(match_manip& operator= (match_manip const&))
70     };
71 
72     template <typename Expr, typename Skipper, typename Attribute>
73     struct match_manip<Expr, mpl::true_, mpl::false_, Skipper, Attribute>
74     {
match_manipboost::spirit::qi::detail::match_manip75         match_manip(Expr const& xpr, Skipper const& s, Attribute& a)
76           : expr(xpr), skipper(s), attr(a), post_skip(skip_flag::postskip) {}
77 
match_manipboost::spirit::qi::detail::match_manip78         match_manip(Expr const& xpr, Skipper const& s
79             , BOOST_SCOPED_ENUM(skip_flag) ps, Attribute& a)
80           : expr(xpr), skipper(s), attr(a), post_skip(ps) {}
81 
82         Expr expr;
83         Skipper const& skipper;
84         Attribute& attr;
85         BOOST_SCOPED_ENUM(skip_flag) const post_skip;
86 
87         // silence MSVC warning C4512: assignment operator could not be generated
88         BOOST_DELETED_FUNCTION(match_manip& operator= (match_manip const&))
89     };
90 
91     ///////////////////////////////////////////////////////////////////////////
92     template <typename Expr, typename Enable = void>
93     struct match
94     {
95         // Report invalid expression error as early as possible.
96         // If you got an error_invalid_expression error message here,
97         // then the expression (expr) is not a valid spirit qi expression.
98         // Did you intend to use the auto_ facilities while forgetting to
99         // #include <boost/spirit/include/qi_match_auto.hpp>?
100         BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
101     };
102 
103     template <typename Expr>
104     struct match<Expr
105       , typename enable_if<traits::matches<qi::domain, Expr> >::type>
106     {
107         typedef match_manip<Expr> type;
108 
callboost::spirit::qi::detail::match109         static type call(Expr const& expr)
110         {
111             return type(expr, unused, unused);
112         }
113     };
114 
115     ///////////////////////////////////////////////////////////////////////////
116     template <typename Expr, typename Skipper, typename Enable = void>
117     struct phrase_match
118     {
119         // Report invalid expression error as early as possible.
120         // If you got an error_invalid_expression error message here,
121         // then the expression (expr) is not a valid spirit qi expression.
122         // Did you intend to use the auto_ facilities while forgetting to
123         // #include <boost/spirit/include/qi_match_auto.hpp>?
124         BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
125     };
126 
127     template <typename Expr, typename Skipper>
128     struct phrase_match<Expr, Skipper
129       , typename enable_if<traits::matches<qi::domain, Expr> >::type>
130     {
131         typedef match_manip<Expr, mpl::false_, mpl::false_, Skipper> type;
132 
callboost::spirit::qi::detail::phrase_match133         static type call(
134             Expr const& expr
135           , Skipper const& skipper
136           , BOOST_SCOPED_ENUM(skip_flag) post_skip)
137         {
138             // Report invalid expression error as early as possible.
139             // If you got an error_invalid_expression error message here,
140             // then the delimiter is not a valid spirit karma expression.
141             BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
142             return type(expr, skipper, post_skip, unused);
143         }
144     };
145 
146     ///////////////////////////////////////////////////////////////////////////
147     template<typename Char, typename Traits, typename Expr
148       , typename CopyExpr, typename CopyAttr>
149     inline std::basic_istream<Char, Traits> &
operator >>(std::basic_istream<Char,Traits> & is,match_manip<Expr,CopyExpr,CopyAttr> const & fm)150     operator>>(std::basic_istream<Char, Traits> &is,
151         match_manip<Expr, CopyExpr, CopyAttr> const& fm)
152     {
153         typedef spirit::basic_istream_iterator<Char, Traits> input_iterator;
154 
155         input_iterator f(is);
156         input_iterator l;
157         if (!qi::parse(f, l, fm.expr))
158         {
159             is.setstate(std::ios_base::failbit);
160         }
161         return is;
162     }
163 
164     ///////////////////////////////////////////////////////////////////////////
165     template<typename Char, typename Traits, typename Expr
166       , typename CopyExpr, typename CopyAttr
167       , typename Attribute>
168     inline std::basic_istream<Char, Traits> &
operator >>(std::basic_istream<Char,Traits> & is,match_manip<Expr,CopyExpr,CopyAttr,unused_type,Attribute> const & fm)169     operator>>(std::basic_istream<Char, Traits> &is,
170         match_manip<Expr, CopyExpr, CopyAttr, unused_type, Attribute> const& fm)
171     {
172         typedef spirit::basic_istream_iterator<Char, Traits> input_iterator;
173 
174         input_iterator f(is);
175         input_iterator l;
176         if (!qi::parse(f, l, fm.expr, fm.attr))
177         {
178             is.setstate(std::ios_base::failbit);
179         }
180         return is;
181     }
182 
183     ///////////////////////////////////////////////////////////////////////////
184     template<typename Char, typename Traits, typename Expr
185       , typename CopyExpr, typename CopyAttr
186       , typename Skipper>
187     inline std::basic_istream<Char, Traits> &
operator >>(std::basic_istream<Char,Traits> & is,match_manip<Expr,CopyExpr,CopyAttr,Skipper> const & fm)188     operator>>(std::basic_istream<Char, Traits> &is,
189         match_manip<Expr, CopyExpr, CopyAttr, Skipper> const& fm)
190     {
191         typedef spirit::basic_istream_iterator<Char, Traits> input_iterator;
192 
193         input_iterator f(is);
194         input_iterator l;
195         if (!qi::phrase_parse(
196                 f, l, fm.expr, fm.skipper, fm.post_skip))
197         {
198             is.setstate(std::ios_base::failbit);
199         }
200         return is;
201     }
202 
203     ///////////////////////////////////////////////////////////////////////////
204     template<typename Char, typename Traits, typename Expr
205       , typename CopyExpr, typename CopyAttr
206       , typename Attribute, typename Skipper
207     >
208     inline std::basic_istream<Char, Traits> &
operator >>(std::basic_istream<Char,Traits> & is,match_manip<Expr,CopyExpr,CopyAttr,Attribute,Skipper> const & fm)209     operator>>(
210         std::basic_istream<Char, Traits> &is,
211         match_manip<Expr, CopyExpr, CopyAttr, Attribute, Skipper> const& fm)
212     {
213         typedef spirit::basic_istream_iterator<Char, Traits> input_iterator;
214 
215         input_iterator f(is);
216         input_iterator l;
217         if (!qi::phrase_parse(
218                 f, l, fm.expr, fm.skipper, fm.post_skip, fm.attr))
219         {
220             is.setstate(std::ios_base::failbit);
221         }
222         return is;
223     }
224 
225 }}}}
226 
227 #endif
228