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