Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:51

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // width_of.hpp
0003 //
0004 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_XPRESSIVE_DETAIL_STATIC_WIDTH_OF_HPP_EAN_10_04_2005
0009 #define BOOST_XPRESSIVE_DETAIL_STATIC_WIDTH_OF_HPP_EAN_10_04_2005
0010 
0011 // MS compatible compilers support #pragma once
0012 #if defined(_MSC_VER)
0013 # pragma once
0014 #endif
0015 
0016 #include <boost/ref.hpp>
0017 #include <boost/mpl/if.hpp>
0018 #include <boost/mpl/or.hpp>
0019 #include <boost/mpl/plus.hpp>
0020 #include <boost/mpl/times.hpp>
0021 #include <boost/mpl/assert.hpp>
0022 #include <boost/mpl/size_t.hpp>
0023 #include <boost/mpl/equal_to.hpp>
0024 #include <boost/type_traits/is_same.hpp>
0025 #include <boost/xpressive/detail/detail_fwd.hpp>
0026 #include <boost/xpressive/detail/static/type_traits.hpp>
0027 #include <boost/proto/traits.hpp>
0028 
0029 namespace boost { namespace xpressive { namespace detail
0030 {
0031     template<typename Expr, typename Char, typename Tag = typename Expr::proto_tag>
0032     struct width_of;
0033 
0034     ///////////////////////////////////////////////////////////////////////////////
0035     // add_widths
0036     //
0037     template<std::size_t N, std::size_t M>
0038     struct add_widths
0039       : mpl::size_t<N + M>
0040     {};
0041 
0042     template<std::size_t M>
0043     struct add_widths<unknown_width::value, M>
0044       : unknown_width
0045     {};
0046 
0047     template<std::size_t N>
0048     struct add_widths<N, unknown_width::value>
0049       : unknown_width
0050     {};
0051 
0052     template<>
0053     struct add_widths<unknown_width::value, unknown_width::value>
0054       : unknown_width
0055     {};
0056 
0057     ///////////////////////////////////////////////////////////////////////////////
0058     // or_widths
0059     //
0060     template<std::size_t N, std::size_t M>
0061     struct or_widths
0062       : unknown_width
0063     {};
0064 
0065     template<std::size_t N>
0066     struct or_widths<N, N>
0067       : mpl::size_t<N>
0068     {};
0069 
0070     ///////////////////////////////////////////////////////////////////////////////
0071     // width_of_terminal
0072     //
0073     template<typename Expr, typename Char, bool IsXpr = is_xpr<Expr>::value>
0074     struct width_of_terminal
0075       : mpl::size_t<Expr::width>    // xpressive literals
0076     {};
0077 
0078     template<typename Expr, typename Char>
0079     struct width_of_terminal<Expr, Char, false>
0080       : unknown_width       // unknown literals (eg, basic_string, basic_regex, etc.)
0081     {};
0082 
0083     template<typename Char>
0084     struct width_of_terminal<Char, Char, false>
0085       : mpl::size_t<1>      // char literals
0086     {};
0087 
0088     template<typename Char>
0089     struct width_of_terminal<char, Char, false>
0090       : mpl::size_t<1>      // char literals
0091     {};
0092 
0093     template<>
0094     struct width_of_terminal<char, char, false>
0095       : mpl::size_t<1>      // char literals
0096     {};
0097 
0098     template<typename Elem, std::size_t N, typename Char>
0099     struct width_of_terminal<Elem (&) [N], Char, false>
0100       : mpl::size_t<N-is_char<Elem>::value>    // string literals
0101     {};
0102 
0103     template<typename Elem, std::size_t N, typename Char>
0104     struct width_of_terminal<Elem const (&) [N], Char, false>
0105       : mpl::size_t<N-is_char<Elem>::value>    // string literals
0106     {};
0107 
0108     ///////////////////////////////////////////////////////////////////////////////
0109     // width_of
0110     //
0111     template<typename Expr, typename Char, typename Tag>
0112     struct width_of
0113     {};
0114 
0115     template<typename Expr, typename Char>
0116     struct width_of<Expr, Char, proto::tag::terminal>
0117       : width_of_terminal<typename proto::result_of::value<Expr>::type, Char>
0118     {};
0119 
0120     template<typename Expr, typename Char>
0121     struct width_of<Expr, Char, proto::tag::shift_right>
0122       : add_widths<
0123             width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>::value
0124           , width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>::value
0125         >
0126     {};
0127 
0128     template<typename Expr, typename Char>
0129     struct width_of<Expr, Char, proto::tag::bitwise_or>
0130       : or_widths<
0131             width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>::value
0132           , width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>::value
0133         >
0134     {};
0135 
0136     template<typename Expr, typename Char, typename Left>
0137     struct width_of_assign
0138     {};
0139 
0140     template<typename Expr, typename Char>
0141     struct width_of_assign<Expr, Char, mark_placeholder>
0142       : width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
0143     {};
0144 
0145     template<typename Expr, typename Char>
0146     struct width_of_assign<Expr, Char, set_initializer>
0147       : mpl::size_t<1>
0148     {};
0149 
0150     template<typename Expr, typename Char, typename Nbr>
0151     struct width_of_assign<Expr, Char, attribute_placeholder<Nbr> >
0152       : unknown_width
0153     {};
0154 
0155     // either (s1 = ...) or (a1 = ...) or (set = ...)
0156     template<typename Expr, typename Char>
0157     struct width_of<Expr, Char, proto::tag::assign>
0158       : width_of_assign<
0159             Expr
0160           , Char
0161           , typename proto::result_of::value<
0162                 typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr
0163             >::type
0164         >
0165     {};
0166 
0167     template<typename Expr, typename Char>
0168     struct width_of<Expr, Char, modifier_tag>
0169       : width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
0170     {};
0171 
0172     template<typename Expr, typename Char>
0173     struct width_of<Expr, Char, lookahead_tag>
0174       : mpl::size_t<0>
0175     {};
0176 
0177     template<typename Expr, typename Char>
0178     struct width_of<Expr, Char, lookbehind_tag>
0179       : mpl::size_t<0>
0180     {};
0181 
0182     // keep() is used to turn off backtracking, so they should only be used
0183     // for things that are variable-width (eg. quantified)
0184     template<typename Expr, typename Char>
0185     struct width_of<Expr, Char, keeper_tag>
0186       : unknown_width
0187     {
0188         // TODO: keep() now has a second meaning: execute actions immediately.
0189         // In that sense, it is perfectly reasonable to put a fixed-width
0190         // sub-expression in a keep. Can fixed-width keep() sub-expressions
0191         // use the simple_repeat_matcher?
0192     };
0193 
0194     template<typename Expr, typename Char>
0195     struct width_of<Expr, Char, proto::tag::unary_plus>
0196       : unknown_width
0197     {};
0198 
0199     template<typename Expr, typename Char>
0200     struct width_of<Expr, Char, proto::tag::dereference>
0201       : unknown_width
0202     {};
0203 
0204     template<typename Expr, typename Char>
0205     struct width_of<Expr, Char, proto::tag::logical_not>
0206       : unknown_width
0207     {};
0208 
0209     template<typename Expr, typename Char, uint_t Min, uint_t Max>
0210     struct width_of<Expr, Char, generic_quant_tag<Min, Max> >
0211       : unknown_width
0212     {};
0213 
0214     template<typename Expr, typename Char, uint_t Count>
0215     struct width_of<Expr, Char, generic_quant_tag<Count, Count> >
0216       : mpl::if_c<
0217             mpl::equal_to<unknown_width, width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char> >::value
0218           , unknown_width
0219           , mpl::times<
0220                 width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
0221               , mpl::size_t<Count>
0222             >
0223         >::type
0224     {};
0225 
0226     template<typename Expr, typename Char>
0227     struct width_of<Expr, Char, proto::tag::negate>
0228       : width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
0229     {};
0230 
0231     // when complementing a set or an assertion, the width is that of the set (1) or the assertion (0)
0232     template<typename Expr, typename Char>
0233     struct width_of<Expr, Char, proto::tag::complement>
0234       : width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
0235     {};
0236 
0237     // The comma is used in list-initialized sets, and the width of sets are 1
0238     template<typename Expr, typename Char>
0239     struct width_of<Expr, Char, proto::tag::comma>
0240       : mpl::size_t<1>
0241     {};
0242 
0243     // The subscript operator[] is used for sets, as in set['a' | range('b','h')],
0244     // or for actions as in (any >> expr)[ action ]
0245     template<typename Expr, typename Char, typename Left>
0246     struct width_of_subscript
0247       : width_of<Left, Char>
0248     {};
0249 
0250     template<typename Expr, typename Char>
0251     struct width_of_subscript<Expr, Char, set_initializer_type>
0252       : mpl::size_t<1>
0253     {
0254         // If Left is "set" then make sure that Right has a width_of 1
0255         BOOST_MPL_ASSERT_RELATION(
0256             1
0257           , ==
0258           , (width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>::value));
0259     };
0260 
0261     template<typename Expr, typename Char>
0262     struct width_of<Expr, Char, proto::tag::subscript>
0263       : width_of_subscript<Expr, Char, typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr>
0264     {};
0265 
0266 }}} // namespace boost::xpressive::detail
0267 
0268 #undef UNREF
0269 
0270 #endif