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     private:
50         // silence MSVC warning C4512: assignment operator could not be generated
51         match_manip& operator= (match_manip const&);
52     };
53 
54     template <typename Expr, typename Skipper, typename Attribute>
55     struct match_manip<Expr, mpl::false_, mpl::true_, Skipper, Attribute>
56     {
match_manipboost::spirit::qi::detail::match_manip57         match_manip(Expr const& xpr, Skipper const& s, Attribute& a)
58           : expr(xpr), skipper(s), attr(a), post_skip(skip_flag::postskip) {}
59 
match_manipboost::spirit::qi::detail::match_manip60         match_manip(Expr const& xpr, Skipper const& s
61             , BOOST_SCOPED_ENUM(skip_flag) ps, Attribute& a)
62           : expr(xpr), skipper(s), attr(a), post_skip(ps) {}
63 
64         Expr const& expr;
65         Skipper const& skipper;
66         Attribute attr;
67         BOOST_SCOPED_ENUM(skip_flag) const post_skip;
68 
69     private:
70         // silence MSVC warning C4512: assignment operator could not be generated
71         match_manip& operator= (match_manip const&);
72     };
73 
74     template <typename Expr, typename Skipper, typename Attribute>
75     struct match_manip<Expr, mpl::true_, mpl::false_, Skipper, Attribute>
76     {
match_manipboost::spirit::qi::detail::match_manip77         match_manip(Expr const& xpr, Skipper const& s, Attribute& a)
78           : expr(xpr), skipper(s), attr(a), post_skip(skip_flag::postskip) {}
79 
match_manipboost::spirit::qi::detail::match_manip80         match_manip(Expr const& xpr, Skipper const& s
81             , BOOST_SCOPED_ENUM(skip_flag) ps, Attribute& a)
82           : expr(xpr), skipper(s), attr(a), post_skip(ps) {}
83 
84         Expr expr;
85         Skipper const& skipper;
86         Attribute& attr;
87         BOOST_SCOPED_ENUM(skip_flag) const post_skip;
88 
89     private:
90         // silence MSVC warning C4512: assignment operator could not be generated
91         match_manip& operator= (match_manip const&);
92     };
93 
94     ///////////////////////////////////////////////////////////////////////////
95     template <typename Expr, typename Enable = void>
96     struct match
97     {
98         // Report invalid expression error as early as possible.
99         // If you got an error_invalid_expression error message here,
100         // then the expression (expr) is not a valid spirit qi expression.
101         // Did you intend to use the auto_ facilities while forgetting to
102         // #include <boost/spirit/include/qi_match_auto.hpp>?
103         BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
104     };
105 
106     template <typename Expr>
107     struct match<Expr
108       , typename enable_if<traits::matches<qi::domain, Expr> >::type>
109     {
110         typedef match_manip<Expr> type;
111 
callboost::spirit::qi::detail::match112         static type call(Expr const& expr)
113         {
114             return type(expr, unused, unused);
115         }
116     };
117 
118     ///////////////////////////////////////////////////////////////////////////
119     template <typename Expr, typename Skipper, typename Enable = void>
120     struct phrase_match
121     {
122         // Report invalid expression error as early as possible.
123         // If you got an error_invalid_expression error message here,
124         // then the expression (expr) is not a valid spirit qi expression.
125         // Did you intend to use the auto_ facilities while forgetting to
126         // #include <boost/spirit/include/qi_match_auto.hpp>?
127         BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
128     };
129 
130     template <typename Expr, typename Skipper>
131     struct phrase_match<Expr, Skipper
132       , typename enable_if<traits::matches<qi::domain, Expr> >::type>
133     {
134         typedef match_manip<Expr, mpl::false_, mpl::false_, Skipper> type;
135 
callboost::spirit::qi::detail::phrase_match136         static type call(
137             Expr const& expr
138           , Skipper const& skipper
139           , BOOST_SCOPED_ENUM(skip_flag) post_skip)
140         {
141             // Report invalid expression error as early as possible.
142             // If you got an error_invalid_expression error message here,
143             // then the delimiter is not a valid spirit karma expression.
144             BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
145             return type(expr, skipper, post_skip, unused);
146         }
147     };
148 
149     ///////////////////////////////////////////////////////////////////////////
150     template<typename Char, typename Traits, typename Expr
151       , typename CopyExpr, typename CopyAttr>
152     inline std::basic_istream<Char, Traits> &
operator >>(std::basic_istream<Char,Traits> & is,match_manip<Expr,CopyExpr,CopyAttr> const & fm)153     operator>>(std::basic_istream<Char, Traits> &is,
154         match_manip<Expr, CopyExpr, CopyAttr> const& fm)
155     {
156         typedef spirit::basic_istream_iterator<Char, Traits> input_iterator;
157 
158         input_iterator f(is);
159         input_iterator l;
160         if (!qi::parse(f, l, fm.expr))
161         {
162             is.setstate(std::ios_base::failbit);
163         }
164         return is;
165     }
166 
167     ///////////////////////////////////////////////////////////////////////////
168     template<typename Char, typename Traits, typename Expr
169       , typename CopyExpr, typename CopyAttr
170       , typename Attribute>
171     inline std::basic_istream<Char, Traits> &
operator >>(std::basic_istream<Char,Traits> & is,match_manip<Expr,CopyExpr,CopyAttr,unused_type,Attribute> const & fm)172     operator>>(std::basic_istream<Char, Traits> &is,
173         match_manip<Expr, CopyExpr, CopyAttr, unused_type, Attribute> const& fm)
174     {
175         typedef spirit::basic_istream_iterator<Char, Traits> input_iterator;
176 
177         input_iterator f(is);
178         input_iterator l;
179         if (!qi::parse(f, l, fm.expr, fm.attr))
180         {
181             is.setstate(std::ios_base::failbit);
182         }
183         return is;
184     }
185 
186     ///////////////////////////////////////////////////////////////////////////
187     template<typename Char, typename Traits, typename Expr
188       , typename CopyExpr, typename CopyAttr
189       , typename Skipper>
190     inline std::basic_istream<Char, Traits> &
operator >>(std::basic_istream<Char,Traits> & is,match_manip<Expr,CopyExpr,CopyAttr,Skipper> const & fm)191     operator>>(std::basic_istream<Char, Traits> &is,
192         match_manip<Expr, CopyExpr, CopyAttr, Skipper> const& fm)
193     {
194         typedef spirit::basic_istream_iterator<Char, Traits> input_iterator;
195 
196         input_iterator f(is);
197         input_iterator l;
198         if (!qi::phrase_parse(
199                 f, l, fm.expr, fm.skipper, fm.post_skip))
200         {
201             is.setstate(std::ios_base::failbit);
202         }
203         return is;
204     }
205 
206     ///////////////////////////////////////////////////////////////////////////
207     template<typename Char, typename Traits, typename Expr
208       , typename CopyExpr, typename CopyAttr
209       , typename Attribute, typename Skipper
210     >
211     inline std::basic_istream<Char, Traits> &
operator >>(std::basic_istream<Char,Traits> & is,match_manip<Expr,CopyExpr,CopyAttr,Attribute,Skipper> const & fm)212     operator>>(
213         std::basic_istream<Char, Traits> &is,
214         match_manip<Expr, CopyExpr, CopyAttr, Attribute, Skipper> const& fm)
215     {
216         typedef spirit::basic_istream_iterator<Char, Traits> input_iterator;
217 
218         input_iterator f(is);
219         input_iterator l;
220         if (!qi::phrase_parse(
221                 f, l, fm.expr, fm.skipper, fm.post_skip, fm.attr))
222         {
223             is.setstate(std::ios_base::failbit);
224         }
225         return is;
226     }
227 
228 }}}}
229 
230 #endif
231