Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Copyright (c) 2001-2011 Joel de Guzman
|
Chris@16
|
3 Copyright (c) 2001-2011 Hartmut Kaiser
|
Chris@16
|
4 Copyright (c) 2010 Bryce Lelbach
|
Chris@16
|
5
|
Chris@16
|
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 ==============================================================================*/
|
Chris@16
|
9 #if !defined(BOOST_SPIRIT_LIT_APR_18_2006_1125PM)
|
Chris@16
|
10 #define BOOST_SPIRIT_LIT_APR_18_2006_1125PM
|
Chris@16
|
11
|
Chris@16
|
12 #if defined(_MSC_VER)
|
Chris@16
|
13 #pragma once
|
Chris@16
|
14 #endif
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/spirit/home/qi/domain.hpp>
|
Chris@16
|
17 #include <boost/spirit/home/qi/skip_over.hpp>
|
Chris@16
|
18 #include <boost/spirit/home/qi/detail/string_parse.hpp>
|
Chris@16
|
19 #include <boost/spirit/home/qi/parser.hpp>
|
Chris@16
|
20 #include <boost/spirit/home/qi/meta_compiler.hpp>
|
Chris@16
|
21 #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
|
Chris@16
|
22 #include <boost/spirit/home/qi/detail/enable_lit.hpp>
|
Chris@16
|
23 #include <boost/spirit/home/support/info.hpp>
|
Chris@16
|
24 #include <boost/spirit/home/support/char_class.hpp>
|
Chris@16
|
25 #include <boost/spirit/home/support/modify.hpp>
|
Chris@16
|
26 #include <boost/spirit/home/support/unused.hpp>
|
Chris@16
|
27 #include <boost/spirit/home/support/common_terminals.hpp>
|
Chris@16
|
28 #include <boost/spirit/home/support/string_traits.hpp>
|
Chris@16
|
29 #include <boost/spirit/home/support/detail/get_encoding.hpp>
|
Chris@16
|
30 #include <boost/spirit/home/support/handles_container.hpp>
|
Chris@16
|
31 #include <boost/fusion/include/at.hpp>
|
Chris@16
|
32 #include <boost/fusion/include/value_at.hpp>
|
Chris@16
|
33 #include <boost/type_traits/add_reference.hpp>
|
Chris@16
|
34 #include <boost/type_traits/add_const.hpp>
|
Chris@16
|
35 #include <boost/mpl/assert.hpp>
|
Chris@16
|
36 #include <boost/mpl/if.hpp>
|
Chris@16
|
37 #include <boost/detail/workaround.hpp>
|
Chris@16
|
38 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
39 #include <string>
|
Chris@16
|
40
|
Chris@16
|
41 namespace boost { namespace spirit
|
Chris@16
|
42 {
|
Chris@16
|
43 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
44 // Enablers
|
Chris@16
|
45 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
46 template <typename T>
|
Chris@16
|
47 struct use_terminal<qi::domain, T
|
Chris@16
|
48 , typename enable_if<traits::is_string<T> >::type> // enables strings
|
Chris@16
|
49 : mpl::true_ {};
|
Chris@16
|
50
|
Chris@16
|
51 template <typename CharEncoding, typename A0>
|
Chris@16
|
52 struct use_terminal<qi::domain
|
Chris@16
|
53 , terminal_ex<
|
Chris@16
|
54 tag::char_code<tag::string, CharEncoding> // enables string(str)
|
Chris@16
|
55 , fusion::vector1<A0> >
|
Chris@16
|
56 > : traits::is_string<A0> {};
|
Chris@16
|
57
|
Chris@16
|
58 template <typename CharEncoding> // enables string(f)
|
Chris@16
|
59 struct use_lazy_terminal<
|
Chris@16
|
60 qi::domain
|
Chris@16
|
61 , tag::char_code<tag::string, CharEncoding>
|
Chris@16
|
62 , 1 /*arity*/
|
Chris@16
|
63 > : mpl::true_ {};
|
Chris@16
|
64
|
Chris@16
|
65 // enables lit(...)
|
Chris@16
|
66 template <typename A0>
|
Chris@16
|
67 struct use_terminal<qi::domain
|
Chris@16
|
68 , terminal_ex<tag::lit, fusion::vector1<A0> >
|
Chris@16
|
69 , typename enable_if<traits::is_string<A0> >::type>
|
Chris@16
|
70 : mpl::true_ {};
|
Chris@16
|
71 }}
|
Chris@16
|
72
|
Chris@16
|
73 namespace boost { namespace spirit { namespace qi
|
Chris@16
|
74 {
|
Chris@16
|
75 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
|
Chris@16
|
76 using spirit::lit;
|
Chris@16
|
77 #endif
|
Chris@16
|
78 using spirit::lit_type;
|
Chris@16
|
79
|
Chris@16
|
80 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
81 // Parse for literal strings
|
Chris@16
|
82 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
83 template <typename String, bool no_attribute>
|
Chris@16
|
84 struct literal_string
|
Chris@16
|
85 : primitive_parser<literal_string<String, no_attribute> >
|
Chris@16
|
86 {
|
Chris@16
|
87 typedef typename
|
Chris@16
|
88 remove_const<typename traits::char_type_of<String>::type>::type
|
Chris@16
|
89 char_type;
|
Chris@16
|
90 typedef std::basic_string<char_type> string_type;
|
Chris@16
|
91
|
Chris@16
|
92 literal_string(typename add_reference<String>::type str_)
|
Chris@16
|
93 : str(str_)
|
Chris@16
|
94 {}
|
Chris@16
|
95
|
Chris@16
|
96 template <typename Context, typename Iterator>
|
Chris@16
|
97 struct attribute
|
Chris@16
|
98 {
|
Chris@16
|
99 typedef typename mpl::if_c<
|
Chris@16
|
100 no_attribute, unused_type, string_type>::type
|
Chris@16
|
101 type;
|
Chris@16
|
102 };
|
Chris@16
|
103
|
Chris@16
|
104 template <typename Iterator, typename Context
|
Chris@16
|
105 , typename Skipper, typename Attribute>
|
Chris@16
|
106 bool parse(Iterator& first, Iterator const& last
|
Chris@16
|
107 , Context& /*context*/, Skipper const& skipper, Attribute& attr_) const
|
Chris@16
|
108 {
|
Chris@16
|
109 qi::skip_over(first, last, skipper);
|
Chris@16
|
110 return detail::string_parse(str, first, last, attr_);
|
Chris@16
|
111 }
|
Chris@16
|
112
|
Chris@16
|
113 template <typename Context>
|
Chris@16
|
114 info what(Context& /*context*/) const
|
Chris@16
|
115 {
|
Chris@16
|
116 return info("literal-string", str);
|
Chris@16
|
117 }
|
Chris@16
|
118
|
Chris@16
|
119 String str;
|
Chris@16
|
120
|
Chris@16
|
121 private:
|
Chris@16
|
122 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
123 literal_string& operator= (literal_string const&);
|
Chris@16
|
124 };
|
Chris@16
|
125
|
Chris@16
|
126 template <typename String, bool no_attribute>
|
Chris@16
|
127 struct no_case_literal_string
|
Chris@16
|
128 : primitive_parser<no_case_literal_string<String, no_attribute> >
|
Chris@16
|
129 {
|
Chris@16
|
130 typedef typename
|
Chris@16
|
131 remove_const<typename traits::char_type_of<String>::type>::type
|
Chris@16
|
132 char_type;
|
Chris@16
|
133 typedef std::basic_string<char_type> string_type;
|
Chris@16
|
134
|
Chris@16
|
135 template <typename CharEncoding>
|
Chris@16
|
136 no_case_literal_string(char_type const* in, CharEncoding encoding)
|
Chris@16
|
137 : str_lo(in)
|
Chris@16
|
138 , str_hi(in)
|
Chris@16
|
139 {
|
Chris@16
|
140 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
|
Chris@16
|
141 encoding; // suppresses warning: C4100: 'encoding' : unreferenced formal parameter
|
Chris@16
|
142 #endif
|
Chris@16
|
143 typename string_type::iterator loi = str_lo.begin();
|
Chris@16
|
144 typename string_type::iterator hii = str_hi.begin();
|
Chris@16
|
145
|
Chris@16
|
146 for (; loi != str_lo.end(); ++loi, ++hii, ++in)
|
Chris@16
|
147 {
|
Chris@16
|
148 typedef typename CharEncoding::char_type encoded_char_type;
|
Chris@16
|
149
|
Chris@16
|
150 *loi = static_cast<char_type>(encoding.tolower(encoded_char_type(*loi)));
|
Chris@16
|
151 *hii = static_cast<char_type>(encoding.toupper(encoded_char_type(*hii)));
|
Chris@16
|
152 }
|
Chris@16
|
153 }
|
Chris@16
|
154
|
Chris@16
|
155 template <typename Context, typename Iterator>
|
Chris@16
|
156 struct attribute
|
Chris@16
|
157 {
|
Chris@16
|
158 typedef typename mpl::if_c<
|
Chris@16
|
159 no_attribute, unused_type, string_type>::type
|
Chris@16
|
160 type;
|
Chris@16
|
161 };
|
Chris@16
|
162
|
Chris@16
|
163 template <typename Iterator, typename Context
|
Chris@16
|
164 , typename Skipper, typename Attribute>
|
Chris@16
|
165 bool parse(Iterator& first, Iterator const& last
|
Chris@16
|
166 , Context& /*context*/, Skipper const& skipper, Attribute& attr_) const
|
Chris@16
|
167 {
|
Chris@16
|
168 qi::skip_over(first, last, skipper);
|
Chris@16
|
169 return detail::string_parse(str_lo, str_hi, first, last, attr_);
|
Chris@16
|
170 }
|
Chris@16
|
171
|
Chris@16
|
172 template <typename Context>
|
Chris@16
|
173 info what(Context& /*context*/) const
|
Chris@16
|
174 {
|
Chris@16
|
175 return info("no-case-literal-string", str_lo);
|
Chris@16
|
176 }
|
Chris@16
|
177
|
Chris@16
|
178 string_type str_lo, str_hi;
|
Chris@16
|
179 };
|
Chris@16
|
180
|
Chris@16
|
181 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
182 // Parser generators: make_xxx function (objects)
|
Chris@16
|
183 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
184 template <typename T, typename Modifiers>
|
Chris@16
|
185 struct make_primitive<T, Modifiers
|
Chris@16
|
186 , typename enable_if<traits::is_string<T> >::type>
|
Chris@16
|
187 {
|
Chris@16
|
188 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
|
Chris@16
|
189
|
Chris@16
|
190 typedef typename add_const<T>::type const_string;
|
Chris@16
|
191 typedef typename mpl::if_<
|
Chris@16
|
192 no_case
|
Chris@16
|
193 , no_case_literal_string<const_string, true>
|
Chris@16
|
194 , literal_string<const_string, true> >::type
|
Chris@16
|
195 result_type;
|
Chris@16
|
196
|
Chris@16
|
197 result_type operator()(
|
Chris@16
|
198 typename add_reference<const_string>::type str, unused_type) const
|
Chris@16
|
199 {
|
Chris@16
|
200 return op(str, no_case());
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 template <typename String>
|
Chris@16
|
204 result_type op(String const& str, mpl::false_) const
|
Chris@16
|
205 {
|
Chris@16
|
206 return result_type(str);
|
Chris@16
|
207 }
|
Chris@16
|
208
|
Chris@16
|
209 template <typename String>
|
Chris@16
|
210 result_type op(String const& str, mpl::true_) const
|
Chris@16
|
211 {
|
Chris@16
|
212 typename spirit::detail::get_encoding<Modifiers,
|
Chris@16
|
213 spirit::char_encoding::standard>::type encoding;
|
Chris@16
|
214 return result_type(traits::get_c_string(str), encoding);
|
Chris@16
|
215 }
|
Chris@16
|
216 };
|
Chris@16
|
217
|
Chris@16
|
218 // lit("...")
|
Chris@16
|
219 template <typename Modifiers, typename A0>
|
Chris@16
|
220 struct make_primitive<
|
Chris@16
|
221 terminal_ex<tag::lit, fusion::vector1<A0> >
|
Chris@16
|
222 , Modifiers
|
Chris@16
|
223 , typename enable_if<traits::is_string<A0> >::type>
|
Chris@16
|
224 {
|
Chris@16
|
225 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
|
Chris@16
|
226
|
Chris@16
|
227 typedef typename add_const<A0>::type const_string;
|
Chris@16
|
228 typedef typename mpl::if_<
|
Chris@16
|
229 no_case
|
Chris@16
|
230 , no_case_literal_string<const_string, true>
|
Chris@16
|
231 , literal_string<const_string, true> >::type
|
Chris@16
|
232 result_type;
|
Chris@16
|
233
|
Chris@16
|
234 template <typename Terminal>
|
Chris@16
|
235 result_type operator()(Terminal const& term, unused_type) const
|
Chris@16
|
236 {
|
Chris@16
|
237 return op(fusion::at_c<0>(term.args), no_case());
|
Chris@16
|
238 }
|
Chris@16
|
239
|
Chris@16
|
240 template <typename String>
|
Chris@16
|
241 result_type op(String const& str, mpl::false_) const
|
Chris@16
|
242 {
|
Chris@16
|
243 return result_type(str);
|
Chris@16
|
244 }
|
Chris@16
|
245
|
Chris@16
|
246 template <typename String>
|
Chris@16
|
247 result_type op(String const& str, mpl::true_) const
|
Chris@16
|
248 {
|
Chris@16
|
249 typedef typename traits::char_encoding_from_char<
|
Chris@16
|
250 typename traits::char_type_of<A0>::type>::type encoding_type;
|
Chris@16
|
251 typename spirit::detail::get_encoding<Modifiers,
|
Chris@16
|
252 encoding_type>::type encoding;
|
Chris@16
|
253 return result_type(traits::get_c_string(str), encoding);
|
Chris@16
|
254 }
|
Chris@16
|
255 };
|
Chris@16
|
256
|
Chris@16
|
257 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
258 // string("...")
|
Chris@16
|
259 template <typename CharEncoding, typename Modifiers, typename A0>
|
Chris@16
|
260 struct make_primitive<
|
Chris@16
|
261 terminal_ex<
|
Chris@16
|
262 tag::char_code<tag::string, CharEncoding>
|
Chris@16
|
263 , fusion::vector1<A0> >
|
Chris@16
|
264 , Modifiers>
|
Chris@16
|
265 {
|
Chris@16
|
266 typedef CharEncoding encoding;
|
Chris@16
|
267 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
|
Chris@16
|
268
|
Chris@16
|
269 typedef typename add_const<A0>::type const_string;
|
Chris@16
|
270 typedef typename mpl::if_<
|
Chris@16
|
271 no_case
|
Chris@16
|
272 , no_case_literal_string<const_string, false>
|
Chris@16
|
273 , literal_string<const_string, false> >::type
|
Chris@16
|
274 result_type;
|
Chris@16
|
275
|
Chris@16
|
276 template <typename Terminal>
|
Chris@16
|
277 result_type operator()(Terminal const& term, unused_type) const
|
Chris@16
|
278 {
|
Chris@16
|
279 return op(fusion::at_c<0>(term.args), no_case());
|
Chris@16
|
280 }
|
Chris@16
|
281
|
Chris@16
|
282 template <typename String>
|
Chris@16
|
283 result_type op(String const& str, mpl::false_) const
|
Chris@16
|
284 {
|
Chris@16
|
285 return result_type(str);
|
Chris@16
|
286 }
|
Chris@16
|
287
|
Chris@16
|
288 template <typename String>
|
Chris@16
|
289 result_type op(String const& str, mpl::true_) const
|
Chris@16
|
290 {
|
Chris@16
|
291 return result_type(traits::get_c_string(str), encoding());
|
Chris@16
|
292 }
|
Chris@16
|
293 };
|
Chris@16
|
294 }}}
|
Chris@16
|
295
|
Chris@16
|
296 namespace boost { namespace spirit { namespace traits
|
Chris@16
|
297 {
|
Chris@16
|
298 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
299 template <typename String, bool no_attribute, typename Attribute
|
Chris@16
|
300 ,typename Context, typename Iterator>
|
Chris@16
|
301 struct handles_container<qi::literal_string<String, no_attribute>
|
Chris@16
|
302 , Attribute, Context, Iterator>
|
Chris@16
|
303 : mpl::true_ {};
|
Chris@16
|
304
|
Chris@16
|
305 template <typename String, bool no_attribute, typename Attribute
|
Chris@16
|
306 , typename Context, typename Iterator>
|
Chris@16
|
307 struct handles_container<qi::no_case_literal_string<String, no_attribute>
|
Chris@16
|
308 , Attribute, Context, Iterator>
|
Chris@16
|
309 : mpl::true_ {};
|
Chris@16
|
310 }}}
|
Chris@16
|
311
|
Chris@16
|
312 #endif
|