File indexing completed on 2025-01-31 10:02:36
0001
0002
0003
0004
0005
0006
0007 #if !defined(BOOST_SPIRIT_X3_ALTERNATIVE_DETAIL_JAN_07_2013_1245PM)
0008 #define BOOST_SPIRIT_X3_ALTERNATIVE_DETAIL_JAN_07_2013_1245PM
0009
0010 #include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
0011 #include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp>
0012 #include <boost/spirit/home/x3/support/traits/is_variant.hpp>
0013 #include <boost/spirit/home/x3/support/traits/tuple_traits.hpp>
0014 #include <boost/spirit/home/x3/support/traits/move_to.hpp>
0015 #include <boost/spirit/home/x3/support/traits/variant_has_substitute.hpp>
0016 #include <boost/spirit/home/x3/support/traits/variant_find_substitute.hpp>
0017 #include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
0018
0019 #include <boost/mpl/if.hpp>
0020
0021 #include <boost/fusion/include/front.hpp>
0022
0023 #include <boost/type_traits/is_same.hpp>
0024 #include <type_traits>
0025
0026 namespace boost { namespace spirit { namespace x3
0027 {
0028 template <typename Left, typename Right>
0029 struct alternative;
0030 }}}
0031
0032 namespace boost { namespace spirit { namespace x3 { namespace detail
0033 {
0034 struct pass_variant_unused
0035 {
0036 typedef unused_type type;
0037
0038 template <typename T>
0039 static unused_type
0040 call(T&)
0041 {
0042 return unused_type();
0043 }
0044 };
0045
0046 template <typename Attribute>
0047 struct pass_variant_used
0048 {
0049 typedef Attribute& type;
0050
0051 static Attribute&
0052 call(Attribute& v)
0053 {
0054 return v;
0055 }
0056 };
0057
0058 template <>
0059 struct pass_variant_used<unused_type> : pass_variant_unused {};
0060
0061 template <typename Parser, typename Attribute, typename Context
0062 , typename Enable = void>
0063 struct pass_parser_attribute
0064 {
0065 typedef typename
0066 traits::attribute_of<Parser, Context>::type
0067 attribute_type;
0068 typedef typename
0069 traits::variant_find_substitute<Attribute, attribute_type>::type
0070 substitute_type;
0071
0072 typedef typename
0073 mpl::if_<
0074 is_same<Attribute, substitute_type>
0075 , Attribute&
0076 , substitute_type
0077 >::type
0078 type;
0079
0080 template <typename Attribute_>
0081 static Attribute_&
0082 call(Attribute_& attribute, mpl::true_)
0083 {
0084 return attribute;
0085 }
0086
0087 template <typename Attribute_>
0088 static type
0089 call(Attribute_&, mpl::false_)
0090 {
0091 return type();
0092 }
0093
0094 template <typename Attribute_>
0095 static type
0096 call(Attribute_& attribute)
0097 {
0098 return call(attribute, is_same<Attribute_, typename remove_reference<type>::type>());
0099 }
0100 };
0101
0102
0103 template <typename Parser, typename Attribute, typename Context
0104 , typename Enable = void>
0105 struct pass_non_variant_attribute
0106 {
0107 typedef Attribute& type;
0108
0109 static Attribute&
0110 call(Attribute& attribute)
0111 {
0112 return attribute;
0113 }
0114 };
0115
0116
0117 template <typename Parser, typename Attribute, typename Context>
0118 struct pass_non_variant_attribute<Parser, Attribute, Context,
0119 typename enable_if<traits::is_size_one_sequence<Attribute>>::type>
0120 {
0121 typedef typename remove_reference<
0122 typename fusion::result_of::front<Attribute>::type>::type
0123 attr_type;
0124
0125 typedef pass_parser_attribute<Parser, attr_type, Context> pass;
0126 typedef typename pass::type type;
0127
0128 template <typename Attribute_>
0129 static type
0130 call(Attribute_& attr)
0131 {
0132 return pass::call(fusion::front(attr));
0133 }
0134 };
0135
0136 template <typename Parser, typename Attribute, typename Context>
0137 struct pass_parser_attribute<Parser, Attribute, Context,
0138 typename enable_if_c<(!traits::is_variant<Attribute>::value)>::type>
0139 : pass_non_variant_attribute<Parser, Attribute, Context>
0140 {};
0141
0142 template <typename Parser, typename Context>
0143 struct pass_parser_attribute<Parser, unused_type, Context>
0144 : pass_variant_unused {};
0145
0146 template <typename Parser, typename Attribute, typename Context>
0147 struct pass_variant_attribute :
0148 mpl::if_c<traits::has_attribute<Parser, Context>::value
0149 , pass_parser_attribute<Parser, Attribute, Context>
0150 , pass_variant_unused>::type
0151 {
0152 };
0153
0154 template <typename L, typename R, typename Attribute, typename Context>
0155 struct pass_variant_attribute<alternative<L, R>, Attribute, Context> :
0156 mpl::if_c<traits::has_attribute<alternative<L, R>, Context>::value
0157 , pass_variant_used<Attribute>
0158 , pass_variant_unused>::type
0159 {
0160 };
0161
0162 template <bool Condition>
0163 struct move_if
0164 {
0165 template<typename T1, typename T2>
0166 static void call(T1& , T2& ) {}
0167 };
0168
0169 template <>
0170 struct move_if<true>
0171 {
0172 template<typename T1, typename T2>
0173 static void call(T1& attr_, T2& attribute)
0174 {
0175 traits::move_to(attr_, attribute);
0176 }
0177 };
0178
0179 template <typename Parser, typename Iterator, typename Context
0180 , typename RContext, typename Attribute>
0181 bool parse_alternative(Parser const& p, Iterator& first, Iterator const& last
0182 , Context const& context, RContext& rcontext, Attribute& attribute)
0183 {
0184 using pass = detail::pass_variant_attribute<Parser, Attribute, Context>;
0185 using pseudo = traits::pseudo_attribute<Context, typename pass::type, Iterator>;
0186
0187 typename pseudo::type attr_ = pseudo::call(first, last, pass::call(attribute));
0188
0189 if (p.parse(first, last, context, rcontext, attr_))
0190 {
0191 move_if<!std::is_reference<decltype(attr_)>::value>::call(attr_, attribute);
0192 return true;
0193 }
0194 return false;
0195 }
0196
0197 template <typename Subject>
0198 struct alternative_helper : unary_parser<Subject, alternative_helper<Subject>>
0199 {
0200 static bool const is_pass_through_unary = true;
0201
0202 using unary_parser<Subject, alternative_helper<Subject>>::unary_parser;
0203
0204 template <typename Iterator, typename Context
0205 , typename RContext, typename Attribute>
0206 bool parse(Iterator& first, Iterator const& last
0207 , Context const& context, RContext& rcontext, Attribute& attr) const
0208 {
0209 return detail::parse_alternative(this->subject, first, last, context, rcontext, attr);
0210 }
0211 };
0212
0213 template <typename Left, typename Right, typename Context, typename RContext>
0214 struct parse_into_container_impl<alternative<Left, Right>, Context, RContext>
0215 {
0216 typedef alternative<Left, Right> parser_type;
0217
0218 template <typename Iterator, typename Attribute>
0219 static bool call(
0220 parser_type const& parser
0221 , Iterator& first, Iterator const& last
0222 , Context const& context, RContext& rcontext, Attribute& attribute, mpl::false_)
0223 {
0224 return detail::parse_into_container(parser.left, first, last, context, rcontext, attribute)
0225 || detail::parse_into_container(parser.right, first, last, context, rcontext, attribute);
0226 }
0227
0228 template <typename Iterator, typename Attribute>
0229 static bool call(
0230 parser_type const& parser
0231 , Iterator& first, Iterator const& last
0232 , Context const& context, RContext& rcontext, Attribute& attribute, mpl::true_)
0233 {
0234 return detail::parse_into_container(alternative_helper<Left>{parser.left}, first, last, context, rcontext, attribute)
0235 || detail::parse_into_container(alternative_helper<Right>{parser.right}, first, last, context, rcontext, attribute);
0236 }
0237
0238 template <typename Iterator, typename Attribute>
0239 static bool call(
0240 parser_type const& parser
0241 , Iterator& first, Iterator const& last
0242 , Context const& context, RContext& rcontext, Attribute& attribute)
0243 {
0244 return call(parser, first, last, context, rcontext, attribute,
0245 typename traits::is_variant<typename traits::container_value<Attribute>::type>::type{});
0246 }
0247 };
0248
0249 }}}}
0250
0251 #endif