Fixes for BOOST_SPIRIT_DEFINE [was: Spirit X3 with on_success() calls on VS2015]

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

Fixes for BOOST_SPIRIT_DEFINE [was: Spirit X3 with on_success() calls on VS2015]

Mikael Asplund

Yes, MSVC is terrible, comparatively... but it has a marvelous development environment and great code generation, once you can get it to actually grok your code. :-)  I'm going to await feedback from Microsoft on my bug report, before I dig any deeper into possible fixes for the on_success problem.

Oki, so... as mentioned in my previous mail, I'm using my own macro instead of BOOST_SPIRIT_DEFINE() since it doesn't work on VS2015.

This is the macro I'm using:

#define SPIRIT_DEFINE_WITH_TYPE_AND_INIT(rule_name, rule_type, init_func)         \
  template <typename Iterator, typename Context, typename Attribute>              \
  bool parse_rule(rule_type, Iterator& first, Iterator const& last,               \
                         Context const& context, Attribute& attr)                 \
    {                                                                             \
      using boost::spirit::x3::unused;                                            \
      static auto const def_ = (rule_name = init_func());                         \
      return def_.parse(first, last, context, unused, attr);                      \
    }                                                                             \

(Wow, that looks terrible in my mail client...)
Called like so:

SPIRIT_DEFINE_WITH_TYPE_AND_INIT(identifier, identifier_type, [&]() { return identifier_def; });

The reason for this is twofold; I need to work around VS2015's broken decltype (second parameter), and I need to sometimes delay initialization of my rule definitions by wrapping them in a function.

Spirit x3 unfortunately pretty much forces one to use global variables as rule definitions, which is a pain is your rules have any sort of dependency on another global variable, which is not in the same file. In my case I had global tokens that needed to be initialized before the rules were initialized, and since the initialization order between files is "random", that created a problem for me. The solution: create the rules at first use by initializer functions.

So... Joel, I would like to suggest the following upgrade to the BOOST_SPIRIT_DEFINE_ macro, which solves both my problems (in the case of MSVC only, if you follow naming strictly at least):

// *******************************************

template <bool b>
struct fetch_rule_definition {
  template <typename T>
  static auto call(const T& def) {
    return def;

template <>
struct fetch_rule_definition<true> {
  template <typename T>
  static auto call(T& def) {
    return def();

#define RULE_TO_TYPE(rule_name) BOOST_PP_CAT(rule_name, _type)
#define RULE_TO_TYPE(rule_name) decltype(rule_name)

#define BOOST_SPIRIT_DEFINE_(r, data, rule_name)                                \
    template <typename Iterator, typename Context, typename Attribute>          \
    inline bool parse_rule(                                                     \
        RULE_TO_TYPE(rule_name) rule_                                           \
      , Iterator& first, Iterator const& last                                   \
      , Context const& context, Attribute& attr)                                \
    {                                                                           \
        using boost::spirit::x3::unused;                                        \
        using boost::is_function;                                               \
        typedef decltype(BOOST_PP_CAT(rule_name, _def)) def_type;               \
        typedef fetch_rule_definition<is_function<def_type>::value> fetch_type; \
        static auto const def_                                                  \
               = (rule_name = fetch_type::call(BOOST_PP_CAT(rule_name, _def))); \
        return def_.parse(first, last, context, unused, attr);                  \
    }                                                                           \

// *******************************************

This allows the following code (changed from your AST example in the documentation) to work:

// *******************************************
  using rexpr_value_type = x3::rule<class rexpr_value, ast::rexpr_value>;
  using rexpr_type = x3::rule<class rexpr, ast::rexpr>;
  using rexpr_key_value_type = x3::rule<class rexpr_key_value, ast::rexpr_key_value>;

  rexpr_value_type     rexpr_value     = "rexpr_value";
  rexpr_type           rexpr           = "rexpr";
  rexpr_key_value_type rexpr_key_value = "rexpr_key_value";

  auto const quoted_string = lexeme['"' >> *(char_ - '"') >> '"'];

  auto const rexpr_value_def
    = quoted_string | rexpr;

  auto rexpr_key_value_def() {
    return quoted_string >> '=' >> rexpr_value;
  auto rexpr_def() {
    return '{' >> *rexpr_key_value >> '}';

  BOOST_SPIRIT_DEFINE(rexpr_value, rexpr, rexpr_key_value);
// *******************************************

This works on MSVC, and it should work on proper compilers too. So... I actually haven't even read how to submit changes, and this isn't even the devel list (I should go join that...). If you need the patch some other way to be able to accept it, let me know... but, how does this look to you? Worth a go? Would be wonderful for me!


-----Original Message-----
From: Joel de Guzman [mailto:[hidden email]]
Sent: Friday, March 18, 2016 02:45
To: [hidden email]
Subject: Re: [Spirit-general] Spirit X3 with on_success() calls on VS2015

On 17/03/2016 10:54 PM, Mikael Asplund wrote:
> Hi!
> I seem to have run into a bug in spirit x3 (or more likely in VS2015,
> but there is no workaround in spirit).
> This results in my on_success() not being called on Windows.  I'm
> looking into this, but wanted to ask if someone have seen this before
> and is aware of this problem and why it occurs? Maybe someone with more knowledge is this area that can figure it out quickly?

Wow, I applaud your heroic efforts. I wish I can help more but I've given up on this compiler a long time ago. This compiler reminds me of endless days trying to figure out ICEs.

Joel de Guzman

Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
Spirit-general mailing list
[hidden email]