Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:09:12

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 //  Copyright (c)      2010 Bryce Lelbach
0003 //
0004 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #if !defined(BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM)
0008 #define BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM
0009 
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013 
0014 #include <boost/spirit/home/support/common_terminals.hpp>
0015 #include <boost/spirit/home/support/string_traits.hpp>
0016 #include <boost/spirit/home/support/info.hpp>
0017 #include <boost/spirit/home/support/char_class.hpp>
0018 #include <boost/spirit/home/support/detail/get_encoding.hpp>
0019 #include <boost/spirit/home/support/char_set/basic_chset.hpp>
0020 #include <boost/spirit/home/karma/domain.hpp>
0021 #include <boost/spirit/home/karma/meta_compiler.hpp>
0022 #include <boost/spirit/home/karma/delimit_out.hpp>
0023 #include <boost/spirit/home/karma/char/char_generator.hpp>
0024 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
0025 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
0026 #include <boost/spirit/home/karma/detail/generate_to.hpp>
0027 #include <boost/spirit/home/karma/detail/enable_lit.hpp>
0028 #include <boost/fusion/include/at.hpp>
0029 #include <boost/fusion/include/vector.hpp>
0030 #include <boost/fusion/include/cons.hpp>
0031 #include <boost/mpl/if.hpp>
0032 #include <boost/mpl/assert.hpp>
0033 #include <boost/mpl/bool.hpp>
0034 #include <boost/utility/enable_if.hpp>
0035 #include <string>
0036 
0037 ///////////////////////////////////////////////////////////////////////////////
0038 namespace boost { namespace spirit
0039 {
0040     ///////////////////////////////////////////////////////////////////////////
0041     // Enablers
0042     ///////////////////////////////////////////////////////////////////////////
0043     template <typename CharEncoding>
0044     struct use_terminal<karma::domain
0045       , tag::char_code<tag::char_, CharEncoding>        // enables char_
0046     > : mpl::true_ {};
0047 
0048     template <typename CharEncoding, typename A0>
0049     struct use_terminal<karma::domain
0050       , terminal_ex<
0051             tag::char_code<tag::char_, CharEncoding>    // enables char_('x'), char_("x")
0052           , fusion::vector1<A0>
0053         >
0054     > : mpl::true_ {};
0055 
0056     template <typename A0>
0057     struct use_terminal<karma::domain
0058           , terminal_ex<tag::lit, fusion::vector1<A0> > // enables lit('x')
0059           , typename enable_if<traits::is_char<A0> >::type>
0060       : mpl::true_ {};
0061 
0062     template <typename CharEncoding, typename A0, typename A1>
0063     struct use_terminal<karma::domain
0064       , terminal_ex<
0065             tag::char_code<tag::char_, CharEncoding>    // enables char_('a','z')
0066           , fusion::vector2<A0, A1>
0067         >
0068     > : mpl::true_ {};
0069 
0070     template <typename CharEncoding>                    // enables *lazy* char_('x'), char_("x")
0071     struct use_lazy_terminal<
0072         karma::domain
0073       , tag::char_code<tag::char_, CharEncoding>
0074       , 1 // arity
0075     > : mpl::true_ {};
0076 
0077     template <>
0078     struct use_terminal<karma::domain, char>            // enables 'x'
0079       : mpl::true_ {};
0080 
0081     template <>
0082     struct use_terminal<karma::domain, char[2]>         // enables "x"
0083       : mpl::true_ {};
0084 
0085     template <>
0086     struct use_terminal<karma::domain, wchar_t>         // enables L'x'
0087       : mpl::true_ {};
0088 
0089     template <>
0090     struct use_terminal<karma::domain, wchar_t[2]>      // enables L"x"
0091       : mpl::true_ {};
0092 }}
0093 
0094 ///////////////////////////////////////////////////////////////////////////////
0095 namespace boost { namespace spirit { namespace karma
0096 {
0097 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0098     using spirit::lit;    // lit('x') is equivalent to 'x'
0099 #endif
0100     using spirit::lit_type;
0101 
0102     ///////////////////////////////////////////////////////////////////////////
0103     //
0104     //  any_char
0105     //      generates a single character from the associated attribute
0106     //
0107     //      Note: this generator has to have an associated attribute
0108     //
0109     ///////////////////////////////////////////////////////////////////////////
0110     template <typename CharEncoding, typename Tag>
0111     struct any_char
0112       : char_generator<any_char<CharEncoding, Tag>, CharEncoding, Tag>
0113     {
0114         typedef typename CharEncoding::char_type char_type;
0115         typedef CharEncoding char_encoding;
0116 
0117         template <typename Context, typename Unused>
0118         struct attribute
0119         {
0120             typedef char_type type;
0121         };
0122 
0123         // any_char has an attached parameter
0124         template <typename Attribute, typename CharParam, typename Context>
0125         bool test(Attribute const& attr, CharParam& ch, Context&) const
0126         {
0127             ch = CharParam(attr);
0128             return true;
0129         }
0130 
0131         // any_char has no attribute attached, it needs to have been
0132         // initialized from a direct literal
0133         template <typename CharParam, typename Context>
0134         bool test(unused_type, CharParam&, Context&) const
0135         {
0136             // It is not possible (doesn't make sense) to use char_ without
0137             // providing any attribute, as the generator doesn't 'know' what
0138             // character to output. The following assertion fires if this
0139             // situation is detected in your code.
0140             BOOST_SPIRIT_ASSERT_FAIL(CharParam, char_not_usable_without_attribute, ());
0141             return false;
0142         }
0143 
0144         template <typename Context>
0145         static info what(Context const& /*context*/)
0146         {
0147             return info("any-char");
0148         }
0149     };
0150 
0151     ///////////////////////////////////////////////////////////////////////////
0152     //
0153     //  literal_char
0154     //      generates a single character given by a literal it was initialized
0155     //      from
0156     //
0157     ///////////////////////////////////////////////////////////////////////////
0158     template <typename CharEncoding, typename Tag, bool no_attribute>
0159     struct literal_char
0160       : char_generator<literal_char<CharEncoding, Tag, no_attribute>
0161           , CharEncoding, Tag>
0162     {
0163         typedef typename CharEncoding::char_type char_type;
0164         typedef CharEncoding char_encoding;
0165 
0166         literal_char(char_type ch)
0167           : ch (spirit::char_class::convert<char_encoding>::to(Tag(), ch)) 
0168         {}
0169 
0170         template <typename Context, typename Unused>
0171         struct attribute
0172           : mpl::if_c<no_attribute, unused_type, char_type>
0173         {};
0174 
0175         // A char_('x') which additionally has an associated attribute emits
0176         // its immediate literal only if it matches the attribute, otherwise
0177         // it fails.
0178         // any_char has an attached parameter
0179         template <typename Attribute, typename CharParam, typename Context>
0180         bool test(Attribute const& attr, CharParam& ch_, Context&) const
0181         {
0182             // fail if attribute isn't matched my immediate literal
0183             ch_ = static_cast<char_type>(attr);
0184             return attr == ch;
0185         }
0186 
0187         // A char_('x') without any associated attribute just emits its 
0188         // immediate literal
0189         template <typename CharParam, typename Context>
0190         bool test(unused_type, CharParam& ch_, Context&) const
0191         {
0192             ch_ = ch;
0193             return true;
0194         }
0195 
0196         template <typename Context>
0197         info what(Context const& /*context*/) const
0198         {
0199             return info("literal-char", char_encoding::toucs4(ch));
0200         }
0201 
0202         char_type ch;
0203     };
0204 
0205     ///////////////////////////////////////////////////////////////////////////
0206     // char range generator
0207     template <typename CharEncoding, typename Tag>
0208     struct char_range
0209       : char_generator<char_range<CharEncoding, Tag>, CharEncoding, Tag>
0210     {
0211         typedef typename CharEncoding::char_type char_type;
0212         typedef CharEncoding char_encoding;
0213 
0214         char_range(char_type from, char_type to)
0215           : from(spirit::char_class::convert<char_encoding>::to(Tag(), from))
0216           , to(spirit::char_class::convert<char_encoding>::to(Tag(), to)) 
0217         {}
0218 
0219         // A char_('a', 'z') which has an associated attribute emits it only if 
0220         // it matches the character range, otherwise it fails.
0221         template <typename Attribute, typename CharParam, typename Context>
0222         bool test(Attribute const& attr, CharParam& ch, Context&) const
0223         {
0224             // fail if attribute doesn't belong to character range
0225             ch = attr;
0226             return (from <= char_type(attr)) && (char_type(attr) <= to);
0227         }
0228 
0229         // A char_('a', 'z') without any associated attribute fails compiling
0230         template <typename CharParam, typename Context>
0231         bool test(unused_type, CharParam&, Context&) const
0232         {
0233             // It is not possible (doesn't make sense) to use char_ generators
0234             // without providing any attribute, as the generator doesn't 'know'
0235             // what to output. The following assertion fires if this situation
0236             // is detected in your code.
0237             BOOST_SPIRIT_ASSERT_FAIL(CharParam
0238               , char_range_not_usable_without_attribute, ());
0239             return false;
0240         }
0241 
0242         template <typename Context>
0243         info what(Context& /*context*/) const
0244         {
0245             info result("char-range", char_encoding::toucs4(from));
0246             boost::get<std::string>(result.value) += '-';
0247             boost::get<std::string>(result.value) += to_utf8(char_encoding::toucs4(to));
0248             return result;
0249         }
0250 
0251         char_type from, to;
0252     };
0253 
0254     ///////////////////////////////////////////////////////////////////////////
0255     // character set generator
0256     template <typename CharEncoding, typename Tag, bool no_attribute>
0257     struct char_set
0258       : char_generator<char_set<CharEncoding, Tag, no_attribute>
0259           , CharEncoding, Tag>
0260     {
0261         typedef typename CharEncoding::char_type char_type;
0262         typedef CharEncoding char_encoding;
0263 
0264         template <typename Context, typename Unused>
0265         struct attribute
0266           : mpl::if_c<no_attribute, unused_type, char_type>
0267         {};
0268 
0269         template <typename String>
0270         char_set(String const& str)
0271         {
0272             typedef typename traits::char_type_of<String>::type in_type;
0273 
0274             BOOST_SPIRIT_ASSERT_MSG((
0275                 (sizeof(char_type) == sizeof(in_type))
0276             ), cannot_convert_string, (String));
0277 
0278             typedef spirit::char_class::convert<char_encoding> convert_type;
0279 
0280             char_type const* definition =
0281                 (char_type const*)traits::get_c_string(str);
0282             char_type ch = convert_type::to(Tag(), *definition++);
0283             while (ch)
0284             {
0285                 char_type next = convert_type::to(Tag(), *definition++);
0286                 if (next == '-')
0287                 {
0288                     next = convert_type::to(Tag(), *definition++);
0289                     if (next == 0)
0290                     {
0291                         chset.set(ch);
0292                         chset.set('-');
0293                         break;
0294                     }
0295                     chset.set(ch, next);
0296                 }
0297                 else
0298                 {
0299                     chset.set(ch);
0300                 }
0301                 ch = next;
0302             }
0303         }
0304 
0305         // A char_("a-z") which has an associated attribute emits it only if 
0306         // it matches the character set, otherwise it fails.
0307         template <typename Attribute, typename CharParam, typename Context>
0308         bool test(Attribute const& attr, CharParam& ch, Context&) const
0309         {
0310             // fail if attribute doesn't belong to character set
0311             ch = attr;
0312             return chset.test(char_type(attr));
0313         }
0314 
0315         // A char_("a-z") without any associated attribute fails compiling
0316         template <typename CharParam, typename Context>
0317         bool test(unused_type, CharParam&, Context&) const
0318         {
0319             // It is not possible (doesn't make sense) to use char_ generators
0320             // without providing any attribute, as the generator doesn't 'know'
0321             // what to output. The following assertion fires if this situation
0322             // is detected in your code.
0323             BOOST_SPIRIT_ASSERT_FAIL(CharParam
0324                , char_set_not_usable_without_attribute, ());
0325             return false;
0326         }
0327 
0328         template <typename Context>
0329         info what(Context& /*context*/) const
0330         {
0331             return info("char-set");
0332         }
0333 
0334         support::detail::basic_chset<char_type> chset;
0335     };
0336 
0337     ///////////////////////////////////////////////////////////////////////////
0338     // Generator generators: make_xxx function (objects)
0339     ///////////////////////////////////////////////////////////////////////////
0340     namespace detail
0341     {
0342         template <typename Modifiers, typename Encoding>
0343         struct basic_literal
0344         {
0345             static bool const lower =
0346                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0347             static bool const upper =
0348                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0349 
0350             typedef literal_char<
0351                 typename spirit::detail::get_encoding_with_case<
0352                     Modifiers, Encoding, lower || upper>::type
0353               , typename get_casetag<Modifiers, lower || upper>::type
0354               , true>
0355             result_type;
0356 
0357             template <typename Char>
0358             result_type operator()(Char ch, unused_type) const
0359             {
0360                 return result_type(ch);
0361             }
0362 
0363             template <typename Char>
0364             result_type operator()(Char const* str, unused_type) const
0365             {
0366                 return result_type(str[0]);
0367             }
0368         };
0369     }
0370 
0371     // literals: 'x', "x"
0372     template <typename Modifiers>
0373     struct make_primitive<char, Modifiers>
0374       : detail::basic_literal<Modifiers, char_encoding::standard> {};
0375 
0376     template <typename Modifiers>
0377     struct make_primitive<char const(&)[2], Modifiers>
0378       : detail::basic_literal<Modifiers, char_encoding::standard> {};
0379 
0380     // literals: L'x', L"x"
0381     template <typename Modifiers>
0382     struct make_primitive<wchar_t, Modifiers>
0383       : detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
0384 
0385     template <typename Modifiers>
0386     struct make_primitive<wchar_t const(&)[2], Modifiers>
0387       : detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
0388 
0389     // char_
0390     template <typename CharEncoding, typename Modifiers>
0391     struct make_primitive<tag::char_code<tag::char_, CharEncoding>, Modifiers>
0392     {
0393         static bool const lower =
0394             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0395         static bool const upper =
0396             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0397 
0398         typedef any_char<
0399             typename spirit::detail::get_encoding_with_case<
0400                 Modifiers, CharEncoding, lower || upper>::type
0401           , typename detail::get_casetag<Modifiers, lower || upper>::type
0402         > result_type;
0403 
0404         result_type operator()(unused_type, unused_type) const
0405         {
0406             return result_type();
0407         }
0408     };
0409 
0410     ///////////////////////////////////////////////////////////////////////////
0411     namespace detail
0412     {
0413         template <typename CharEncoding, typename Modifiers, typename A0
0414           , bool no_attribute>
0415         struct make_char_direct
0416         {
0417             static bool const lower =
0418                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0419             static bool const upper =
0420                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0421 
0422             typedef typename spirit::detail::get_encoding_with_case<
0423                 Modifiers, CharEncoding, lower || upper>::type encoding;
0424             typedef typename detail::get_casetag<
0425                 Modifiers, lower || upper>::type tag;
0426 
0427             typedef typename mpl::if_<
0428                 traits::is_string<A0>
0429               , char_set<encoding, tag, no_attribute>
0430               , literal_char<encoding, tag, no_attribute>
0431             >::type result_type;
0432 
0433             template <typename Terminal>
0434             result_type operator()(Terminal const& term, unused_type) const
0435             {
0436                 return result_type(fusion::at_c<0>(term.args));
0437             }
0438         };
0439     }
0440 
0441     // char_(...), lit(...)
0442     template <typename CharEncoding, typename Modifiers, typename A0>
0443     struct make_primitive<
0444             terminal_ex<
0445                 tag::char_code<tag::char_, CharEncoding>
0446               , fusion::vector1<A0> >
0447           , Modifiers>
0448       : detail::make_char_direct<CharEncoding, Modifiers, A0, false>
0449     {};
0450 
0451     template <typename Modifiers, typename A0>
0452     struct make_primitive<
0453             terminal_ex<tag::lit, fusion::vector1<A0> >
0454           , Modifiers
0455           , typename enable_if<traits::is_char<A0> >::type>
0456       : detail::make_char_direct<
0457             typename traits::char_encoding_from_char<
0458                 typename traits::char_type_of<A0>::type>::type
0459           , Modifiers, A0, true>
0460     {};
0461 
0462     ///////////////////////////////////////////////////////////////////////////
0463     // char_("x")
0464     template <typename CharEncoding, typename Modifiers, typename Char>
0465     struct make_primitive<
0466         terminal_ex<
0467             tag::char_code<tag::char_, CharEncoding>
0468           , fusion::vector1<Char(&)[2]> > // For single char strings
0469       , Modifiers>
0470     {
0471         static bool const lower =
0472             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0473         static bool const upper =
0474             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0475 
0476         typedef literal_char<
0477             typename spirit::detail::get_encoding_with_case<
0478                 Modifiers, CharEncoding, lower || upper>::type
0479           , typename detail::get_casetag<Modifiers, lower || upper>::type
0480           , false
0481         > result_type;
0482 
0483         template <typename Terminal>
0484         result_type operator()(Terminal const& term, unused_type) const
0485         {
0486             return result_type(fusion::at_c<0>(term.args)[0]);
0487         }
0488     };
0489 
0490     ///////////////////////////////////////////////////////////////////////////
0491     // char_('a', 'z')
0492     template <typename CharEncoding, typename Modifiers, typename A0, typename A1>
0493     struct make_primitive<
0494         terminal_ex<
0495             tag::char_code<tag::char_, CharEncoding>
0496           , fusion::vector2<A0, A1>
0497         >
0498       , Modifiers>
0499     {
0500         static bool const lower =
0501             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0502         static bool const upper =
0503             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0504 
0505         typedef char_range<
0506             typename spirit::detail::get_encoding_with_case<
0507                 Modifiers, CharEncoding, lower || upper>::type
0508           , typename detail::get_casetag<Modifiers, lower || upper>::type
0509         > result_type;
0510 
0511         template <typename Terminal>
0512         result_type operator()(Terminal const& term, unused_type) const
0513         {
0514             return result_type(fusion::at_c<0>(term.args)
0515               , fusion::at_c<1>(term.args));
0516         }
0517     };
0518 
0519     template <typename CharEncoding, typename Modifiers, typename Char>
0520     struct make_primitive<
0521         terminal_ex<
0522             tag::char_code<tag::char_, CharEncoding>
0523           , fusion::vector2<Char(&)[2], Char(&)[2]> // For single char strings
0524         >
0525       , Modifiers>
0526     {
0527         static bool const lower =
0528             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0529         static bool const upper =
0530             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0531 
0532         typedef char_range<
0533             typename spirit::detail::get_encoding_with_case<
0534                 Modifiers, CharEncoding, lower || upper>::type
0535           , typename detail::get_casetag<Modifiers, lower || upper>::type
0536         > result_type;
0537 
0538         template <typename Terminal>
0539         result_type operator()(Terminal const& term, unused_type) const
0540         {
0541             return result_type(fusion::at_c<0>(term.args)[0]
0542               , fusion::at_c<1>(term.args)[0]);
0543         }
0544     };
0545 }}}   // namespace boost::spirit::karma
0546 
0547 #endif