Mercurial > hg > vamp-build-and-test
diff DEPENDENCIES/generic/include/boost/spirit/home/karma/char/char.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/generic/include/boost/spirit/home/karma/char/char.hpp Tue Aug 05 11:11:38 2014 +0100 @@ -0,0 +1,547 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// Copyright (c) 2010 Bryce Lelbach +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM) +#define BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/support/common_terminals.hpp> +#include <boost/spirit/home/support/string_traits.hpp> +#include <boost/spirit/home/support/info.hpp> +#include <boost/spirit/home/support/char_class.hpp> +#include <boost/spirit/home/support/detail/get_encoding.hpp> +#include <boost/spirit/home/support/char_set/basic_chset.hpp> +#include <boost/spirit/home/karma/domain.hpp> +#include <boost/spirit/home/karma/meta_compiler.hpp> +#include <boost/spirit/home/karma/delimit_out.hpp> +#include <boost/spirit/home/karma/char/char_generator.hpp> +#include <boost/spirit/home/karma/auxiliary/lazy.hpp> +#include <boost/spirit/home/karma/detail/get_casetag.hpp> +#include <boost/spirit/home/karma/detail/generate_to.hpp> +#include <boost/spirit/home/karma/detail/enable_lit.hpp> +#include <boost/fusion/include/at.hpp> +#include <boost/fusion/include/vector.hpp> +#include <boost/fusion/include/cons.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/utility/enable_if.hpp> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit +{ + /////////////////////////////////////////////////////////////////////////// + // Enablers + /////////////////////////////////////////////////////////////////////////// + template <typename CharEncoding> + struct use_terminal<karma::domain + , tag::char_code<tag::char_, CharEncoding> // enables char_ + > : mpl::true_ {}; + + template <typename CharEncoding, typename A0> + struct use_terminal<karma::domain + , terminal_ex< + tag::char_code<tag::char_, CharEncoding> // enables char_('x'), char_("x") + , fusion::vector1<A0> + > + > : mpl::true_ {}; + + template <typename A0> + struct use_terminal<karma::domain + , terminal_ex<tag::lit, fusion::vector1<A0> > // enables lit('x') + , typename enable_if<traits::is_char<A0> >::type> + : mpl::true_ {}; + + template <typename CharEncoding, typename A0, typename A1> + struct use_terminal<karma::domain + , terminal_ex< + tag::char_code<tag::char_, CharEncoding> // enables char_('a','z') + , fusion::vector2<A0, A1> + > + > : mpl::true_ {}; + + template <typename CharEncoding> // enables *lazy* char_('x'), char_("x") + struct use_lazy_terminal< + karma::domain + , tag::char_code<tag::char_, CharEncoding> + , 1 // arity + > : mpl::true_ {}; + + template <> + struct use_terminal<karma::domain, char> // enables 'x' + : mpl::true_ {}; + + template <> + struct use_terminal<karma::domain, char[2]> // enables "x" + : mpl::true_ {}; + + template <> + struct use_terminal<karma::domain, wchar_t> // enables L'x' + : mpl::true_ {}; + + template <> + struct use_terminal<karma::domain, wchar_t[2]> // enables L"x" + : mpl::true_ {}; +}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace karma +{ +#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS + using spirit::lit; // lit('x') is equivalent to 'x' +#endif + using spirit::lit_type; + + /////////////////////////////////////////////////////////////////////////// + // + // any_char + // generates a single character from the associated attribute + // + // Note: this generator has to have an associated attribute + // + /////////////////////////////////////////////////////////////////////////// + template <typename CharEncoding, typename Tag> + struct any_char + : char_generator<any_char<CharEncoding, Tag>, CharEncoding, Tag> + { + typedef typename CharEncoding::char_type char_type; + typedef CharEncoding char_encoding; + + template <typename Context, typename Unused> + struct attribute + { + typedef char_type type; + }; + + // any_char has an attached parameter + template <typename Attribute, typename CharParam, typename Context> + bool test(Attribute const& attr, CharParam& ch, Context&) const + { + ch = CharParam(attr); + return true; + } + + // any_char has no attribute attached, it needs to have been + // initialized from a direct literal + template <typename CharParam, typename Context> + bool test(unused_type, CharParam&, Context&) const + { + // It is not possible (doesn't make sense) to use char_ without + // providing any attribute, as the generator doesn't 'know' what + // character to output. The following assertion fires if this + // situation is detected in your code. + BOOST_SPIRIT_ASSERT_FAIL(CharParam, char_not_usable_without_attribute, ()); + return false; + } + + template <typename Context> + static info what(Context const& /*context*/) + { + return info("any-char"); + } + }; + + /////////////////////////////////////////////////////////////////////////// + // + // literal_char + // generates a single character given by a literal it was initialized + // from + // + /////////////////////////////////////////////////////////////////////////// + template <typename CharEncoding, typename Tag, bool no_attribute> + struct literal_char + : char_generator<literal_char<CharEncoding, Tag, no_attribute> + , CharEncoding, Tag> + { + typedef typename CharEncoding::char_type char_type; + typedef CharEncoding char_encoding; + + literal_char(char_type ch) + : ch (spirit::char_class::convert<char_encoding>::to(Tag(), ch)) + {} + + template <typename Context, typename Unused> + struct attribute + : mpl::if_c<no_attribute, unused_type, char_type> + {}; + + // A char_('x') which additionally has an associated attribute emits + // its immediate literal only if it matches the attribute, otherwise + // it fails. + // any_char has an attached parameter + template <typename Attribute, typename CharParam, typename Context> + bool test(Attribute const& attr, CharParam& ch_, Context&) const + { + // fail if attribute isn't matched my immediate literal + ch_ = attr; + return attr == ch; + } + + // A char_('x') without any associated attribute just emits its + // immediate literal + template <typename CharParam, typename Context> + bool test(unused_type, CharParam& ch_, Context&) const + { + ch_ = ch; + return true; + } + + template <typename Context> + info what(Context const& /*context*/) const + { + return info("literal-char", char_encoding::toucs4(ch)); + } + + char_type ch; + }; + + /////////////////////////////////////////////////////////////////////////// + // char range generator + template <typename CharEncoding, typename Tag> + struct char_range + : char_generator<char_range<CharEncoding, Tag>, CharEncoding, Tag> + { + typedef typename CharEncoding::char_type char_type; + typedef CharEncoding char_encoding; + + char_range(char_type from, char_type to) + : from(spirit::char_class::convert<char_encoding>::to(Tag(), from)) + , to(spirit::char_class::convert<char_encoding>::to(Tag(), to)) + {} + + // A char_('a', 'z') which has an associated attribute emits it only if + // it matches the character range, otherwise it fails. + template <typename Attribute, typename CharParam, typename Context> + bool test(Attribute const& attr, CharParam& ch, Context&) const + { + // fail if attribute doesn't belong to character range + ch = attr; + return (from <= char_type(attr)) && (char_type(attr) <= to); + } + + // A char_('a', 'z') without any associated attribute fails compiling + template <typename CharParam, typename Context> + bool test(unused_type, CharParam&, Context&) const + { + // It is not possible (doesn't make sense) to use char_ generators + // without providing any attribute, as the generator doesn't 'know' + // what to output. The following assertion fires if this situation + // is detected in your code. + BOOST_SPIRIT_ASSERT_FAIL(CharParam + , char_range_not_usable_without_attribute, ()); + return false; + } + + template <typename Context> + info what(Context& /*context*/) const + { + info result("char-range", char_encoding::toucs4(from)); + boost::get<std::string>(result.value) += '-'; + boost::get<std::string>(result.value) += to_utf8(char_encoding::toucs4(to)); + return result; + } + + char_type from, to; + }; + + /////////////////////////////////////////////////////////////////////////// + // character set generator + template <typename CharEncoding, typename Tag, bool no_attribute> + struct char_set + : char_generator<char_set<CharEncoding, Tag, no_attribute> + , CharEncoding, Tag> + { + typedef typename CharEncoding::char_type char_type; + typedef CharEncoding char_encoding; + + template <typename Context, typename Unused> + struct attribute + : mpl::if_c<no_attribute, unused_type, char_type> + {}; + + template <typename String> + char_set(String const& str) + { + typedef typename traits::char_type_of<String>::type in_type; + + BOOST_SPIRIT_ASSERT_MSG(( + (sizeof(char_type) == sizeof(in_type)) + ), cannot_convert_string, (String)); + + typedef spirit::char_class::convert<char_encoding> convert_type; + + char_type const* definition = + (char_type const*)traits::get_c_string(str); + char_type ch = convert_type::to(Tag(), *definition++); + while (ch) + { + char_type next = convert_type::to(Tag(), *definition++); + if (next == '-') + { + next = convert_type::to(Tag(), *definition++); + if (next == 0) + { + chset.set(ch); + chset.set('-'); + break; + } + chset.set(ch, next); + } + else + { + chset.set(ch); + } + ch = next; + } + } + + // A char_("a-z") which has an associated attribute emits it only if + // it matches the character set, otherwise it fails. + template <typename Attribute, typename CharParam, typename Context> + bool test(Attribute const& attr, CharParam& ch, Context&) const + { + // fail if attribute doesn't belong to character set + ch = attr; + return chset.test(char_type(attr)); + } + + // A char_("a-z") without any associated attribute fails compiling + template <typename CharParam, typename Context> + bool test(unused_type, CharParam&, Context&) const + { + // It is not possible (doesn't make sense) to use char_ generators + // without providing any attribute, as the generator doesn't 'know' + // what to output. The following assertion fires if this situation + // is detected in your code. + BOOST_SPIRIT_ASSERT_FAIL(CharParam + , char_set_not_usable_without_attribute, ()); + return false; + } + + template <typename Context> + info what(Context& /*context*/) const + { + return info("char-set"); + } + + support::detail::basic_chset<char_type> chset; + }; + + /////////////////////////////////////////////////////////////////////////// + // Generator generators: make_xxx function (objects) + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename Modifiers, typename Encoding> + struct basic_literal + { + static bool const lower = + has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; + static bool const upper = + has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; + + typedef literal_char< + typename spirit::detail::get_encoding_with_case< + Modifiers, Encoding, lower || upper>::type + , typename get_casetag<Modifiers, lower || upper>::type + , true> + result_type; + + template <typename Char> + result_type operator()(Char ch, unused_type) const + { + return result_type(ch); + } + + template <typename Char> + result_type operator()(Char const* str, unused_type) const + { + return result_type(str[0]); + } + }; + } + + // literals: 'x', "x" + template <typename Modifiers> + struct make_primitive<char, Modifiers> + : detail::basic_literal<Modifiers, char_encoding::standard> {}; + + template <typename Modifiers> + struct make_primitive<char const(&)[2], Modifiers> + : detail::basic_literal<Modifiers, char_encoding::standard> {}; + + // literals: L'x', L"x" + template <typename Modifiers> + struct make_primitive<wchar_t, Modifiers> + : detail::basic_literal<Modifiers, char_encoding::standard_wide> {}; + + template <typename Modifiers> + struct make_primitive<wchar_t const(&)[2], Modifiers> + : detail::basic_literal<Modifiers, char_encoding::standard_wide> {}; + + // char_ + template <typename CharEncoding, typename Modifiers> + struct make_primitive<tag::char_code<tag::char_, CharEncoding>, Modifiers> + { + static bool const lower = + has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; + static bool const upper = + has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; + + typedef any_char< + typename spirit::detail::get_encoding_with_case< + Modifiers, CharEncoding, lower || upper>::type + , typename detail::get_casetag<Modifiers, lower || upper>::type + > result_type; + + result_type operator()(unused_type, unused_type) const + { + return result_type(); + } + }; + + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename CharEncoding, typename Modifiers, typename A0 + , bool no_attribute> + struct make_char_direct + { + static bool const lower = + has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; + static bool const upper = + has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; + + typedef typename spirit::detail::get_encoding_with_case< + Modifiers, CharEncoding, lower || upper>::type encoding; + typedef typename detail::get_casetag< + Modifiers, lower || upper>::type tag; + + typedef typename mpl::if_< + traits::is_string<A0> + , char_set<encoding, tag, no_attribute> + , literal_char<encoding, tag, no_attribute> + >::type result_type; + + template <typename Terminal> + result_type operator()(Terminal const& term, unused_type) const + { + return result_type(fusion::at_c<0>(term.args)); + } + }; + } + + // char_(...), lit(...) + template <typename CharEncoding, typename Modifiers, typename A0> + struct make_primitive< + terminal_ex< + tag::char_code<tag::char_, CharEncoding> + , fusion::vector1<A0> > + , Modifiers> + : detail::make_char_direct<CharEncoding, Modifiers, A0, false> + {}; + + template <typename Modifiers, typename A0> + struct make_primitive< + terminal_ex<tag::lit, fusion::vector1<A0> > + , Modifiers + , typename enable_if<traits::is_char<A0> >::type> + : detail::make_char_direct< + typename traits::char_encoding_from_char< + typename traits::char_type_of<A0>::type>::type + , Modifiers, A0, true> + {}; + + /////////////////////////////////////////////////////////////////////////// + // char_("x") + template <typename CharEncoding, typename Modifiers, typename Char> + struct make_primitive< + terminal_ex< + tag::char_code<tag::char_, CharEncoding> + , fusion::vector1<Char(&)[2]> > // For single char strings + , Modifiers> + { + static bool const lower = + has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; + static bool const upper = + has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; + + typedef literal_char< + typename spirit::detail::get_encoding_with_case< + Modifiers, CharEncoding, lower || upper>::type + , typename detail::get_casetag<Modifiers, lower || upper>::type + , false + > result_type; + + template <typename Terminal> + result_type operator()(Terminal const& term, unused_type) const + { + return result_type(fusion::at_c<0>(term.args)[0]); + } + }; + + /////////////////////////////////////////////////////////////////////////// + // char_('a', 'z') + template <typename CharEncoding, typename Modifiers, typename A0, typename A1> + struct make_primitive< + terminal_ex< + tag::char_code<tag::char_, CharEncoding> + , fusion::vector2<A0, A1> + > + , Modifiers> + { + static bool const lower = + has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; + static bool const upper = + has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; + + typedef char_range< + typename spirit::detail::get_encoding_with_case< + Modifiers, CharEncoding, lower || upper>::type + , typename detail::get_casetag<Modifiers, lower || upper>::type + > result_type; + + template <typename Terminal> + result_type operator()(Terminal const& term, unused_type) const + { + return result_type(fusion::at_c<0>(term.args) + , fusion::at_c<1>(term.args)); + } + }; + + template <typename CharEncoding, typename Modifiers, typename Char> + struct make_primitive< + terminal_ex< + tag::char_code<tag::char_, CharEncoding> + , fusion::vector2<Char(&)[2], Char(&)[2]> // For single char strings + > + , Modifiers> + { + static bool const lower = + has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; + static bool const upper = + has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; + + typedef char_range< + typename spirit::detail::get_encoding_with_case< + Modifiers, CharEncoding, lower || upper>::type + , typename detail::get_casetag<Modifiers, lower || upper>::type + > result_type; + + template <typename Terminal> + result_type operator()(Terminal const& term, unused_type) const + { + return result_type(fusion::at_c<0>(term.args)[0] + , fusion::at_c<1>(term.args)[0]); + } + }; +}}} // namespace boost::spirit::karma + +#endif