2
0
mirror of https://github.com/boostorg/spirit.git synced 2026-01-19 16:52:10 +00:00

bug fix for x3 where container attribute is substitute for the container value type. happens with recursive data structures such as vector<v> where v is a variant that also contains vector<v>.

This commit is contained in:
Joel de Guzman
2015-05-16 23:58:38 +08:00
parent cce02e9d07
commit c60d93fff3

View File

@@ -75,6 +75,13 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
}
};
template <typename Parser, typename Container, typename Context>
struct parser_accepts_container
: traits::is_substitute<
typename traits::attribute_of<Parser, Context>::type
, Container
>
{};
template <typename Parser>
struct parse_into_container_base_impl
@@ -84,10 +91,10 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
// Parser has attribute (synthesize; Attribute is a container)
template <typename Iterator, typename Context
, typename RContext, typename Attribute>
static bool call_synthesize(
static bool call_synthesize_x(
Parser const& parser
, Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr)
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
{
// synthesized attribute needs to be value initialized
typedef typename
@@ -103,6 +110,33 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
return true;
}
// Parser has attribute (synthesize; Attribute is a container)
template <typename Iterator, typename Context
, typename RContext, typename Attribute>
static bool call_synthesize_x(
Parser const& parser
, Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
{
return parser.parse(first, last, context, rcontext, attr);
}
// Parser has attribute (synthesize; Attribute is a container)
template <typename Iterator, typename Context
, typename RContext, typename Attribute>
static bool call_synthesize(
Parser const& parser
, Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr)
{
typedef
parser_accepts_container<Parser, Attribute, Context>
parser_accepts_container;
return call_synthesize_x(parser, first, last, context, rcontext, attr
, parser_accepts_container());
}
// Parser has attribute (synthesize; Attribute is a single element fusion sequence)
template <typename Iterator, typename Context
, typename RContext, typename Attribute>
@@ -193,7 +227,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
template <typename Parser, typename Context, typename RContext, typename Enable = void>
struct parse_into_container_impl : parse_into_container_base_impl<Parser> {};
template <typename Parser, typename Container, typename RContext, typename Context>
template <typename Parser, typename Container, typename Context>
struct parser_attr_is_substitute_for_container_value
: traits::is_substitute<
typename traits::attribute_of<Parser, Context>::type
@@ -209,7 +243,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
static bool call(
Parser const& parser
, Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
{
return parse_into_container_base_impl<Parser>::call(
parser, first, last, context, rcontext, attr);
@@ -219,7 +253,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
static bool call(
Parser const& parser
, Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
{
return parser.parse(first, last, context, rcontext, attr);
}
@@ -229,9 +263,21 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
, Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr)
{
typedef parser_accepts_container<
Parser, Attribute, Context>
parser_accepts_container;
typedef parser_attr_is_substitute_for_container_value<
Parser, Attribute, Context>
parser_attr_is_substitute_for_container_value;
typedef mpl::or_<
parser_accepts_container
, mpl::not_<parser_attr_is_substitute_for_container_value>>
pass_attibute_as_is;
return call(parser, first, last, context, rcontext, attr,
parser_attr_is_substitute_for_container_value<
Parser, Attribute, Context, RContext>());
pass_attibute_as_is());
}
};