Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:36

0001 /*=============================================================================
0002     Copyright (c) 2001-2014 Joel de Guzman
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_X3_RULE_JAN_08_2012_0326PM)
0008 #define BOOST_SPIRIT_X3_RULE_JAN_08_2012_0326PM
0009 
0010 #include <boost/spirit/home/x3/nonterminal/detail/rule.hpp>
0011 #include <boost/type_traits/is_same.hpp>
0012 #include <boost/spirit/home/x3/support/context.hpp>
0013 #include <boost/preprocessor/variadic/to_seq.hpp>
0014 #include <boost/preprocessor/variadic/elem.hpp>
0015 #include <boost/preprocessor/seq/for_each.hpp>
0016 #include <type_traits>
0017 
0018 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
0019 #include <typeinfo>
0020 #endif
0021 
0022 namespace boost { namespace spirit { namespace x3
0023 {
0024     // default parse_rule implementation
0025     template <typename ID, typename Iterator
0026       , typename Context, typename ActualAttribute>
0027     inline detail::default_parse_rule_result
0028     parse_rule(
0029         detail::rule_id<ID>
0030       , Iterator& first, Iterator const& last
0031       , Context const& context, ActualAttribute& attr)
0032     {
0033         static_assert(!is_same<decltype(x3::get<ID>(context)), unused_type>::value,
0034             "BOOST_SPIRIT_DEFINE undefined for this rule.");
0035         return x3::get<ID>(context).parse(first, last, context, unused, attr);
0036     }
0037 
0038     template <typename ID, typename RHS, typename Attribute, bool force_attribute_, bool skip_definition_injection = false>
0039     struct rule_definition : parser<rule_definition<ID, RHS, Attribute, force_attribute_, skip_definition_injection>>
0040     {
0041         typedef rule_definition<ID, RHS, Attribute, force_attribute_, skip_definition_injection> this_type;
0042         typedef ID id;
0043         typedef RHS rhs_type;
0044         typedef rule<ID, Attribute, force_attribute_> lhs_type;
0045         typedef Attribute attribute_type;
0046 
0047         static bool const has_attribute =
0048             !is_same<Attribute, unused_type>::value;
0049         static bool const handles_container =
0050             traits::is_container<Attribute>::value;
0051         static bool const force_attribute =
0052             force_attribute_;
0053 
0054         constexpr rule_definition(RHS const& rhs, char const* name)
0055           : rhs(rhs), name(name) {}
0056 
0057         template <typename Iterator, typename Context, typename Attribute_>
0058         bool parse(Iterator& first, Iterator const& last
0059           , Context const& context, unused_type, Attribute_& attr) const
0060         {
0061             return detail::rule_parser<attribute_type, ID, skip_definition_injection>
0062                 ::call_rule_definition(
0063                     rhs, name, first, last
0064                   , context
0065                   , attr
0066                   , mpl::bool_<force_attribute>());
0067         }
0068 
0069         RHS rhs;
0070         char const* name;
0071     };
0072 
0073     template <typename ID, typename Attribute, bool force_attribute_>
0074     struct rule : parser<rule<ID, Attribute, force_attribute_>>
0075     {
0076         static_assert(!std::is_reference<Attribute>::value,
0077                       "Reference qualifier on rule attribute type is meaningless");
0078 
0079         typedef ID id;
0080         typedef Attribute attribute_type;
0081         static bool const has_attribute =
0082             !std::is_same<std::remove_const_t<Attribute>, unused_type>::value;
0083         static bool const handles_container =
0084             traits::is_container<Attribute>::value;
0085         static bool const force_attribute = force_attribute_;
0086 
0087 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
0088         rule() : name(typeid(rule).name()) {}
0089 #else
0090         constexpr rule() : name("unnamed") {}
0091 #endif
0092 
0093         constexpr rule(char const* name)
0094           : name(name) {}
0095 
0096         constexpr rule(rule const& r)
0097           : name(r.name)
0098         {
0099             // Assert that we are not copying an unitialized static rule. If
0100             // the static is in another TU, it may be initialized after we copy
0101             // it. If so, its name member will be nullptr.
0102             BOOST_ASSERT_MSG(r.name, "uninitialized rule"); // static initialization order fiasco
0103         }
0104 
0105         template <typename RHS>
0106         constexpr rule_definition<
0107             ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_>
0108         operator=(RHS const& rhs) const&
0109         {
0110             return { as_parser(rhs), name };
0111         }
0112 
0113         template <typename RHS>
0114         constexpr rule_definition<
0115             ID, typename extension::as_parser<RHS>::value_type, Attribute, true>
0116         operator%=(RHS const& rhs) const&
0117         {
0118             return { as_parser(rhs), name };
0119         }
0120 
0121         // When a rule placeholder constructed and immediately consumed it cannot be used recursively,
0122         // that's why the rule definition injection into a parser context can be skipped.
0123         // This optimization has a huge impact on compile times because immediate rules are commonly
0124         // used to cast an attribute like `as`/`attr_cast` does in Qi.
0125         template <typename RHS>
0126         constexpr rule_definition<
0127             ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_, true>
0128         operator=(RHS const& rhs) const&&
0129         {
0130             return { as_parser(rhs), name };
0131         }
0132 
0133         template <typename RHS>
0134         constexpr rule_definition<
0135             ID, typename extension::as_parser<RHS>::value_type, Attribute, true, true>
0136         operator%=(RHS const& rhs) const&&
0137         {
0138             return { as_parser(rhs), name };
0139         }
0140 
0141 
0142         template <typename Iterator, typename Context, typename Attribute_>
0143         bool parse(Iterator& first, Iterator const& last
0144           , Context const& context, unused_type, Attribute_& attr) const
0145         {
0146             static_assert(has_attribute,
0147                 "The rule does not have an attribute. Check your parser.");
0148 
0149             using transform = traits::transform_attribute<
0150                 Attribute_, attribute_type, parser_id>;
0151 
0152             using transform_attr = typename transform::type;
0153             transform_attr attr_ = transform::pre(attr);
0154 
0155             if (parse_rule(detail::rule_id<ID>{}, first, last, context, attr_)) {
0156                 transform::post(attr, std::forward<transform_attr>(attr_));
0157                 return true;
0158             }
0159             return false;
0160         }
0161 
0162         template <typename Iterator, typename Context>
0163         bool parse(Iterator& first, Iterator const& last
0164             , Context const& context, unused_type, unused_type) const
0165         {
0166             // make sure we pass exactly the rule attribute type
0167             attribute_type no_attr{};
0168             return parse_rule(detail::rule_id<ID>{}, first, last, context, no_attr);
0169         }
0170 
0171         char const* name;
0172     };
0173 
0174     namespace traits
0175     {
0176         template <typename T, typename Enable = void>
0177         struct is_rule : mpl::false_ {};
0178 
0179         template <typename ID, typename Attribute, bool force_attribute>
0180         struct is_rule<rule<ID, Attribute, force_attribute>> : mpl::true_ {};
0181 
0182         template <typename ID, typename Attribute, typename RHS, bool force_attribute, bool skip_definition_injection>
0183         struct is_rule<rule_definition<ID, RHS, Attribute, force_attribute, skip_definition_injection>> : mpl::true_ {};
0184     }
0185 
0186     template <typename T>
0187     struct get_info<T, typename enable_if<traits::is_rule<T>>::type>
0188     {
0189         typedef std::string result_type;
0190         std::string operator()(T const& r) const
0191         {
0192             BOOST_ASSERT_MSG(r.name, "uninitialized rule"); // static initialization order fiasco
0193             return r.name? r.name : "uninitialized";
0194         }
0195     };
0196 
0197 #define BOOST_SPIRIT_DECLARE_(r, data, rule_type)                               \
0198     template <typename Iterator, typename Context>                              \
0199     bool parse_rule(                                                            \
0200         ::boost::spirit::x3::detail::rule_id<rule_type::id>                     \
0201       , Iterator& first, Iterator const& last                                   \
0202       , Context const& context, rule_type::attribute_type& attr);               \
0203     /***/
0204 
0205 #define BOOST_SPIRIT_DECLARE(...) BOOST_PP_SEQ_FOR_EACH(                        \
0206     BOOST_SPIRIT_DECLARE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))            \
0207     /***/
0208 
0209 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
0210 #define BOOST_SPIRIT_DEFINE_(r, data, rule_name)                                \
0211     using BOOST_PP_CAT(rule_name, _synonym) = decltype(rule_name);              \
0212     template <typename Iterator, typename Context>                              \
0213     inline bool parse_rule(                                                     \
0214         ::boost::spirit::x3::detail::rule_id<BOOST_PP_CAT(rule_name, _synonym)::id> \
0215       , Iterator& first, Iterator const& last                                   \
0216       , Context const& context, BOOST_PP_CAT(rule_name, _synonym)::attribute_type& attr) \
0217     {                                                                           \
0218         using rule_t = BOOST_JOIN(rule_name, _synonym);                         \
0219         return ::boost::spirit::x3::detail                                      \
0220             ::rule_parser<typename rule_t::attribute_type, rule_t::id, true>    \
0221             ::call_rule_definition(                                             \
0222                 BOOST_JOIN(rule_name, _def), rule_name.name                     \
0223               , first, last, context, attr                                      \
0224               , ::boost::mpl::bool_<rule_t::force_attribute>());                \
0225     }                                                                           \
0226     /***/
0227 #else
0228 #define BOOST_SPIRIT_DEFINE_(r, data, rule_name)                                \
0229     template <typename Iterator, typename Context>                              \
0230     inline bool parse_rule(                                                     \
0231         ::boost::spirit::x3::detail::rule_id<decltype(rule_name)::id>           \
0232       , Iterator& first, Iterator const& last                                   \
0233       , Context const& context, decltype(rule_name)::attribute_type& attr)      \
0234     {                                                                           \
0235         using rule_t = decltype(rule_name);                                     \
0236         return ::boost::spirit::x3::detail                                      \
0237             ::rule_parser<typename rule_t::attribute_type, rule_t::id, true>    \
0238             ::call_rule_definition(                                             \
0239                 BOOST_JOIN(rule_name, _def), rule_name.name                     \
0240               , first, last, context, attr                                      \
0241               , ::boost::mpl::bool_<rule_t::force_attribute>());                \
0242     }                                                                           \
0243     /***/
0244 #endif
0245 
0246 #define BOOST_SPIRIT_DEFINE(...) BOOST_PP_SEQ_FOR_EACH(                         \
0247     BOOST_SPIRIT_DEFINE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))             \
0248     /***/
0249 
0250 #define BOOST_SPIRIT_INSTANTIATE(rule_type, Iterator, Context)                  \
0251     template bool parse_rule<Iterator, Context>(                                \
0252         ::boost::spirit::x3::detail::rule_id<rule_type::id>                     \
0253       , Iterator& first, Iterator const& last                                   \
0254       , Context const& context, rule_type::attribute_type&);                    \
0255     /***/
0256 
0257 
0258 }}}
0259 
0260 #endif