namespace boost { namespace spirit { namespace x3
{
// default parse_rule implementation
- template <typename ID, typename Attribute, typename Iterator
+ template <typename ID, typename Iterator
, typename Context, typename ActualAttribute>
inline detail::default_parse_rule_result
parse_rule(
- rule<ID, Attribute> /* rule_ */
+ detail::rule_id<ID>
, Iterator& first, Iterator const& last
, Context const& context, ActualAttribute& attr)
{
- static_assert(!is_same<decltype(get<ID>(context)), unused_type>::value,
+ static_assert(!is_same<decltype(x3::get<ID>(context)), unused_type>::value,
"BOOST_SPIRIT_DEFINE undefined for this rule.");
- return get<ID>(context).parse(first, last, context, unused, attr);
+ return x3::get<ID>(context).parse(first, last, context, unused, attr);
}
- template <typename ID, typename RHS, typename Attribute, bool force_attribute_>
+ template <typename ID, typename RHS, typename Attribute, bool force_attribute_, bool skip_definition_injection = false>
struct rule_definition : parser<rule_definition<ID, RHS, Attribute, force_attribute_>>
{
- typedef rule_definition<ID, RHS, Attribute, force_attribute_> this_type;
+ typedef rule_definition<ID, RHS, Attribute, force_attribute_, skip_definition_injection> this_type;
typedef ID id;
typedef RHS rhs_type;
- typedef rule<ID, Attribute> lhs_type;
+ typedef rule<ID, Attribute, force_attribute_> lhs_type;
typedef Attribute attribute_type;
static bool const has_attribute =
bool parse(Iterator& first, Iterator const& last
, Context const& context, unused_type, Attribute_& attr) const
{
- return detail::rule_parser<attribute_type, ID>
+ return detail::rule_parser<attribute_type, ID, skip_definition_injection>
::call_rule_definition(
rhs, name, first, last
, context
};
template <typename ID, typename Attribute, bool force_attribute_>
- struct rule : parser<rule<ID, Attribute>>
+ struct rule : parser<rule<ID, Attribute, force_attribute_>>
{
static_assert(!std::is_reference<Attribute>::value,
"Reference qualifier on rule attribute type is meaningless");
template <typename RHS>
constexpr rule_definition<
ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_>
- operator=(RHS const& rhs) const
+ operator=(RHS const& rhs) const&
{
return { as_parser(rhs), name };
}
template <typename RHS>
constexpr rule_definition<
ID, typename extension::as_parser<RHS>::value_type, Attribute, true>
- operator%=(RHS const& rhs) const
+ operator%=(RHS const& rhs) const&
+ {
+ return { as_parser(rhs), name };
+ }
+
+ // When a rule placeholder constructed and immediately consumed it cannot be used recursively,
+ // that's why the rule definition injection into a parser context can be skipped.
+ // This optimization has a huge impact on compile times because immediate rules are commonly
+ // used to cast an attribute like `as`/`attr_cast` does in Qi.
+ template <typename RHS>
+ constexpr rule_definition<
+ ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_, true>
+ operator=(RHS const& rhs) const&&
+ {
+ return { as_parser(rhs), name };
+ }
+
+ template <typename RHS>
+ constexpr rule_definition<
+ ID, typename extension::as_parser<RHS>::value_type, Attribute, true, true>
+ operator%=(RHS const& rhs) const&&
{
return { as_parser(rhs), name };
}
using transform_attr = typename transform::type;
transform_attr attr_ = transform::pre(attr);
- if (parse_rule(*this, first, last, context, attr_)) {
+ if (parse_rule(detail::rule_id<ID>{}, first, last, context, attr_)) {
transform::post(attr, std::forward<transform_attr>(attr_));
return true;
}
{
// make sure we pass exactly the rule attribute type
attribute_type no_attr{};
- return parse_rule(*this, first, last, context, no_attr);
+ return parse_rule(detail::rule_id<ID>{}, first, last, context, no_attr);
}
char const* name;
template <typename T, typename Enable = void>
struct is_rule : mpl::false_ {};
- template <typename ID, typename Attribute>
- struct is_rule<rule<ID, Attribute>> : mpl::true_ {};
+ template <typename ID, typename Attribute, bool force_attribute>
+ struct is_rule<rule<ID, Attribute, force_attribute>> : mpl::true_ {};
- template <typename ID, typename Attribute, typename RHS, bool force_attribute>
- struct is_rule<rule_definition<ID, RHS, Attribute, force_attribute>> : mpl::true_ {};
+ template <typename ID, typename Attribute, typename RHS, bool force_attribute, bool skip_definition_injection>
+ struct is_rule<rule_definition<ID, RHS, Attribute, force_attribute, skip_definition_injection>> : mpl::true_ {};
}
template <typename T>
#define BOOST_SPIRIT_DECLARE_(r, data, rule_type) \
template <typename Iterator, typename Context> \
bool parse_rule( \
- rule_type rule_ \
+ ::boost::spirit::x3::detail::rule_id<rule_type::id> \
, Iterator& first, Iterator const& last \
, Context const& context, rule_type::attribute_type& attr); \
/***/
using BOOST_PP_CAT(rule_name, _synonym) = decltype(rule_name); \
template <typename Iterator, typename Context> \
inline bool parse_rule( \
- BOOST_PP_CAT(rule_name, _synonym) /* rule_ */ \
+ ::boost::spirit::x3::detail::rule_id<BOOST_PP_CAT(rule_name, _synonym)::id> \
, Iterator& first, Iterator const& last \
, Context const& context, BOOST_PP_CAT(rule_name, _synonym)::attribute_type& attr) \
{ \
- using boost::spirit::x3::unused; \
- static auto const def_ = (rule_name = BOOST_PP_CAT(rule_name, _def)); \
- return def_.parse(first, last, context, unused, attr); \
+ using rule_t = BOOST_JOIN(rule_name, _synonym); \
+ return ::boost::spirit::x3::detail \
+ ::rule_parser<typename rule_t::attribute_type, rule_t::id, true> \
+ ::call_rule_definition( \
+ BOOST_JOIN(rule_name, _def), rule_name.name \
+ , first, last, context, attr \
+ , ::boost::mpl::bool_<rule_t::force_attribute>()); \
} \
/***/
#else
#define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
template <typename Iterator, typename Context> \
inline bool parse_rule( \
- decltype(rule_name) /* rule_ */ \
+ ::boost::spirit::x3::detail::rule_id<decltype(rule_name)::id> \
, Iterator& first, Iterator const& last \
, Context const& context, decltype(rule_name)::attribute_type& attr) \
{ \
- using boost::spirit::x3::unused; \
- static auto const def_ = (rule_name = BOOST_PP_CAT(rule_name, _def)); \
- return def_.parse(first, last, context, unused, attr); \
+ using rule_t = decltype(rule_name); \
+ return ::boost::spirit::x3::detail \
+ ::rule_parser<typename rule_t::attribute_type, rule_t::id, true> \
+ ::call_rule_definition( \
+ BOOST_JOIN(rule_name, _def), rule_name.name \
+ , first, last, context, attr \
+ , ::boost::mpl::bool_<rule_t::force_attribute>()); \
} \
/***/
#endif
#define BOOST_SPIRIT_INSTANTIATE(rule_type, Iterator, Context) \
template bool parse_rule<Iterator, Context>( \
- rule_type rule_ \
+ ::boost::spirit::x3::detail::rule_id<rule_type::id> \
, Iterator& first, Iterator const& last \
, Context const& context, rule_type::attribute_type&); \
/***/