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 // silence MSVC warning C4512: assignment operator could not be generated 122 BOOST_DELETED_FUNCTION(literal_string& operator= (literal_string const&)) 123 }; 124 125 template <typename String, bool no_attribute> 126 struct no_case_literal_string 127 : primitive_parser<no_case_literal_string<String, no_attribute> > 128 { 129 typedef typename 130 remove_const<typename traits::char_type_of<String>::type>::type 131 char_type; 132 typedef std::basic_string<char_type> string_type; 133 134 template <typename CharEncoding> no_case_literal_stringboost::spirit::qi::no_case_literal_string135 no_case_literal_string(char_type const* in, CharEncoding encoding) 136 : str_lo(in) 137 , str_hi(in) 138 { 139 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) 140 encoding; // suppresses warning: C4100: 'encoding' : unreferenced formal parameter 141 #endif 142 typename string_type::iterator loi = str_lo.begin(); 143 typename string_type::iterator hii = str_hi.begin(); 144 145 for (; loi != str_lo.end(); ++loi, ++hii, ++in) 146 { 147 typedef typename CharEncoding::char_type encoded_char_type; 148 149 *loi = static_cast<char_type>(encoding.tolower(encoded_char_type(*loi))); 150 *hii = static_cast<char_type>(encoding.toupper(encoded_char_type(*hii))); 151 } 152 } 153 154 template <typename Context, typename Iterator> 155 struct attribute 156 { 157 typedef typename mpl::if_c< 158 no_attribute, unused_type, string_type>::type 159 type; 160 }; 161 162 template <typename Iterator, typename Context 163 , typename Skipper, typename Attribute> parseboost::spirit::qi::no_case_literal_string164 bool parse(Iterator& first, Iterator const& last 165 , Context& /*context*/, Skipper const& skipper, Attribute& attr_) const 166 { 167 qi::skip_over(first, last, skipper); 168 return detail::string_parse(str_lo, str_hi, first, last, attr_); 169 } 170 171 template <typename Context> whatboost::spirit::qi::no_case_literal_string172 info what(Context& /*context*/) const 173 { 174 return info("no-case-literal-string", str_lo); 175 } 176 177 string_type str_lo, str_hi; 178 }; 179 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> 186 { 187 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case; 188 189 typedef typename add_const<T>::type const_string; 190 typedef typename mpl::if_< 191 no_case 192 , no_case_literal_string<const_string, true> 193 , literal_string<const_string, true> >::type 194 result_type; 195 operator ()boost::spirit::qi::make_primitive196 result_type operator()( 197 typename add_reference<const_string>::type str, unused_type) const 198 { 199 return op(str, no_case()); 200 } 201 202 template <typename String> opboost::spirit::qi::make_primitive203 result_type op(String const& str, mpl::false_) const 204 { 205 return result_type(str); 206 } 207 208 template <typename String> opboost::spirit::qi::make_primitive209 result_type op(String const& str, mpl::true_) const 210 { 211 typename spirit::detail::get_encoding<Modifiers, 212 spirit::char_encoding::standard>::type encoding; 213 return result_type(traits::get_c_string(str), encoding); 214 } 215 }; 216 217 // lit("...") 218 template <typename Modifiers, typename A0> 219 struct make_primitive< 220 terminal_ex<tag::lit, fusion::vector1<A0> > 221 , Modifiers 222 , typename enable_if<traits::is_string<A0> >::type> 223 { 224 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case; 225 226 typedef typename add_const<A0>::type const_string; 227 typedef typename mpl::if_< 228 no_case 229 , no_case_literal_string<const_string, true> 230 , literal_string<const_string, true> >::type 231 result_type; 232 233 template <typename Terminal> operator ()boost::spirit::qi::make_primitive234 result_type operator()(Terminal const& term, unused_type) const 235 { 236 return op(fusion::at_c<0>(term.args), no_case()); 237 } 238 239 template <typename String> opboost::spirit::qi::make_primitive240 result_type op(String const& str, mpl::false_) const 241 { 242 return result_type(str); 243 } 244 245 template <typename String> opboost::spirit::qi::make_primitive246 result_type op(String const& str, mpl::true_) const 247 { 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); 253 } 254 }; 255 256 /////////////////////////////////////////////////////////////////////////// 257 // string("...") 258 template <typename CharEncoding, typename Modifiers, typename A0> 259 struct make_primitive< 260 terminal_ex< 261 tag::char_code<tag::string, CharEncoding> 262 , fusion::vector1<A0> > 263 , Modifiers> 264 { 265 typedef CharEncoding encoding; 266 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case; 267 268 typedef typename add_const<A0>::type const_string; 269 typedef typename mpl::if_< 270 no_case 271 , no_case_literal_string<const_string, false> 272 , literal_string<const_string, false> >::type 273 result_type; 274 275 template <typename Terminal> operator ()boost::spirit::qi::make_primitive276 result_type operator()(Terminal const& term, unused_type) const 277 { 278 return op(fusion::at_c<0>(term.args), no_case()); 279 } 280 281 template <typename String> opboost::spirit::qi::make_primitive282 result_type op(String const& str, mpl::false_) const 283 { 284 return result_type(str); 285 } 286 287 template <typename String> opboost::spirit::qi::make_primitive288 result_type op(String const& str, mpl::true_) const 289 { 290 return result_type(traits::get_c_string(str), encoding()); 291 } 292 }; 293 }}} 294 295 namespace boost { namespace spirit { namespace traits 296 { 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> 302 : mpl::true_ {}; 303 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> 308 : mpl::true_ {}; 309 }}} 310 311 #endif 312