1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2010 Bryce Lelbach
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 ==============================================================================*/
9 #if !defined(BOOST_SPIRIT_LIT_APR_18_2006_1125PM)
10 #define BOOST_SPIRIT_LIT_APR_18_2006_1125PM
16 #include <boost/spirit/home/qi/domain.hpp>
17 #include <boost/spirit/home/qi/skip_over.hpp>
18 #include <boost/spirit/home/qi/detail/string_parse.hpp>
19 #include <boost/spirit/home/qi/parser.hpp>
20 #include <boost/spirit/home/qi/meta_compiler.hpp>
21 #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
22 #include <boost/spirit/home/qi/detail/enable_lit.hpp>
23 #include <boost/spirit/home/support/info.hpp>
24 #include <boost/spirit/home/support/char_class.hpp>
25 #include <boost/spirit/home/support/modify.hpp>
26 #include <boost/spirit/home/support/unused.hpp>
27 #include <boost/spirit/home/support/common_terminals.hpp>
28 #include <boost/spirit/home/support/string_traits.hpp>
29 #include <boost/spirit/home/support/detail/get_encoding.hpp>
30 #include <boost/spirit/home/support/handles_container.hpp>
31 #include <boost/fusion/include/at.hpp>
32 #include <boost/fusion/include/value_at.hpp>
33 #include <boost/type_traits/add_reference.hpp>
34 #include <boost/type_traits/add_const.hpp>
35 #include <boost/mpl/assert.hpp>
36 #include <boost/mpl/if.hpp>
37 #include <boost/detail/workaround.hpp>
38 #include <boost/utility/enable_if.hpp>
41 namespace boost { namespace spirit
43 ///////////////////////////////////////////////////////////////////////////
45 ///////////////////////////////////////////////////////////////////////////
47 struct use_terminal<qi::domain, T
48 , typename enable_if<traits::is_string<T> >::type> // enables strings
51 template <typename CharEncoding, typename A0>
52 struct use_terminal<qi::domain
54 tag::char_code<tag::string, CharEncoding> // enables string(str)
55 , fusion::vector1<A0> >
56 > : traits::is_string<A0> {};
58 template <typename CharEncoding> // enables string(f)
59 struct use_lazy_terminal<
61 , tag::char_code<tag::string, CharEncoding>
66 template <typename A0>
67 struct use_terminal<qi::domain
68 , terminal_ex<tag::lit, fusion::vector1<A0> >
69 , typename enable_if<traits::is_string<A0> >::type>
73 namespace boost { namespace spirit { namespace qi
75 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
78 using spirit::lit_type;
80 ///////////////////////////////////////////////////////////////////////////
81 // Parse for literal strings
82 ///////////////////////////////////////////////////////////////////////////
83 template <typename String, bool no_attribute>
85 : primitive_parser<literal_string<String, no_attribute> >
88 remove_const<typename traits::char_type_of<String>::type>::type
90 typedef std::basic_string<char_type> string_type;
92 literal_string(typename add_reference<String>::type str_)
96 template <typename Context, typename Iterator>
99 typedef typename mpl::if_c<
100 no_attribute, unused_type, string_type>::type
104 template <typename Iterator, typename Context
105 , typename Skipper, typename Attribute>
106 bool parse(Iterator& first, Iterator const& last
107 , Context& /*context*/, Skipper const& skipper, Attribute& attr_) const
109 qi::skip_over(first, last, skipper);
110 return detail::string_parse(str, first, last, attr_);
113 template <typename Context>
114 info what(Context& /*context*/) const
116 return info("literal-string", str);
121 // silence MSVC warning C4512: assignment operator could not be generated
122 BOOST_DELETED_FUNCTION(literal_string& operator= (literal_string const&))
125 template <typename String, bool no_attribute>
126 struct no_case_literal_string
127 : primitive_parser<no_case_literal_string<String, no_attribute> >
130 remove_const<typename traits::char_type_of<String>::type>::type
132 typedef std::basic_string<char_type> string_type;
134 template <typename CharEncoding>
135 no_case_literal_string(char_type const* in, CharEncoding encoding)
139 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
140 (void)encoding; // suppresses warning: C4100: 'encoding' : unreferenced formal parameter
142 typename string_type::iterator loi = str_lo.begin();
143 typename string_type::iterator hii = str_hi.begin();
145 for (; loi != str_lo.end(); ++loi, ++hii, ++in)
147 typedef typename CharEncoding::char_type encoded_char_type;
149 *loi = static_cast<char_type>(encoding.tolower(encoded_char_type(*loi)));
150 *hii = static_cast<char_type>(encoding.toupper(encoded_char_type(*hii)));
154 template <typename Context, typename Iterator>
157 typedef typename mpl::if_c<
158 no_attribute, unused_type, string_type>::type
162 template <typename Iterator, typename Context
163 , typename Skipper, typename Attribute>
164 bool parse(Iterator& first, Iterator const& last
165 , Context& /*context*/, Skipper const& skipper, Attribute& attr_) const
167 qi::skip_over(first, last, skipper);
168 return detail::string_parse(str_lo, str_hi, first, last, attr_);
171 template <typename Context>
172 info what(Context& /*context*/) const
174 return info("no-case-literal-string", str_lo);
177 string_type str_lo, str_hi;
180 ///////////////////////////////////////////////////////////////////////////
181 // Parser generators: make_xxx function (objects)
182 ///////////////////////////////////////////////////////////////////////////
183 template <typename T, typename Modifiers>
184 struct make_primitive<T, Modifiers
185 , typename enable_if<traits::is_string<T> >::type>
187 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
189 typedef typename add_const<T>::type const_string;
190 typedef typename mpl::if_<
192 , no_case_literal_string<const_string, true>
193 , literal_string<const_string, true> >::type
196 result_type operator()(
197 typename add_reference<const_string>::type str, unused_type) const
199 return op(str, no_case());
202 template <typename String>
203 result_type op(String const& str, mpl::false_) const
205 return result_type(str);
208 template <typename String>
209 result_type op(String const& str, mpl::true_) const
211 typename spirit::detail::get_encoding<Modifiers,
212 spirit::char_encoding::standard>::type encoding;
213 return result_type(traits::get_c_string(str), encoding);
218 template <typename Modifiers, typename A0>
219 struct make_primitive<
220 terminal_ex<tag::lit, fusion::vector1<A0> >
222 , typename enable_if<traits::is_string<A0> >::type>
224 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
226 typedef typename add_const<A0>::type const_string;
227 typedef typename mpl::if_<
229 , no_case_literal_string<const_string, true>
230 , literal_string<const_string, true> >::type
233 template <typename Terminal>
234 result_type operator()(Terminal const& term, unused_type) const
236 return op(fusion::at_c<0>(term.args), no_case());
239 template <typename String>
240 result_type op(String const& str, mpl::false_) const
242 return result_type(str);
245 template <typename String>
246 result_type op(String const& str, mpl::true_) const
248 typedef typename traits::char_encoding_from_char<
249 typename traits::char_type_of<A0>::type>::type encoding_type;
250 typename spirit::detail::get_encoding<Modifiers,
251 encoding_type>::type encoding;
252 return result_type(traits::get_c_string(str), encoding);
256 ///////////////////////////////////////////////////////////////////////////
258 template <typename CharEncoding, typename Modifiers, typename A0>
259 struct make_primitive<
261 tag::char_code<tag::string, CharEncoding>
262 , fusion::vector1<A0> >
265 typedef CharEncoding encoding;
266 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
268 typedef typename add_const<A0>::type const_string;
269 typedef typename mpl::if_<
271 , no_case_literal_string<const_string, false>
272 , literal_string<const_string, false> >::type
275 template <typename Terminal>
276 result_type operator()(Terminal const& term, unused_type) const
278 return op(fusion::at_c<0>(term.args), no_case());
281 template <typename String>
282 result_type op(String const& str, mpl::false_) const
284 return result_type(str);
287 template <typename String>
288 result_type op(String const& str, mpl::true_) const
290 return result_type(traits::get_c_string(str), encoding());
295 namespace boost { namespace spirit { namespace traits
297 ///////////////////////////////////////////////////////////////////////////
298 template <typename String, bool no_attribute, typename Attribute
299 ,typename Context, typename Iterator>
300 struct handles_container<qi::literal_string<String, no_attribute>
301 , Attribute, Context, Iterator>
304 template <typename String, bool no_attribute, typename Attribute
305 , typename Context, typename Iterator>
306 struct handles_container<qi::no_case_literal_string<String, no_attribute>
307 , Attribute, Context, Iterator>