boostorg / spirit

Boost.org spirit module
http://boost.org/libs/spirit
392 stars 161 forks source link

invalid static_cast when using _val = style assignment in semantic action Boost 1.65.1 #411

Closed godmar closed 6 years ago

godmar commented 6 years ago

I apologize if this comes across as a usage question rather than a bug report. I do not understand why this code does not compile and wonder whether it should:

qi::rule<It, std::string()> rule = qi::int_ 
   [ _val = px::bind([](int i) -> std::string { return std::to_string(2*i); }, _1) ];

Full example here

Should it compile? The example is adopted from here and I'll note an analogous example using phx::new_ appears to compile.

If it shouldn't compile, would it be a reasonable enhancement request to support this? Thank you.

Kojoley commented 6 years ago
    qi::rule<It, std::string()> rule = ...
    int data = 99;
    if (parse(f, l, rule, data))

You are asking your parser to assign a string to the integer value. Just replace int data = 99; with std::string data;. https://wandbox.org/#wandbox-resultwindow-code-body-7

godmar commented 6 years ago

I'm so sorry, in my attempt to pare down the actual problem I'm having I went a step too far. The error really occurs not at the top-level where I get the value from the parser, but near the leaves of the grammar. Here's another attempt that hopefully avoids this bug (I have an inner rule that parses a string, but wants to use a semantic action to convert the attribute type from a string to an int. Is that possible? I've looked through the qi tests and didn't see where this is tested.)

    qi::rule<It, std::string()> inputstring;    // produces string as _val
    inputstring %= qi::alpha >> *qi::alnum;

    qi::rule<It, int()> rule;     // produces int as _val
    // convert (std::string _1) to (int _val)
    rule %= inputstring [ _val = px::bind([](std::string &s) -> int { return std::stoi(s); }, _1) ];

    It f = begin(input), l = end(input);
    int data;
    if (parse(f, l, rule, data))        // parse rule which returns an int
        std::cout << "Parsed: " << data << " ";

Corrected example here.

Kojoley commented 6 years ago

Ok, I will look into this a bit later.

godmar commented 6 years ago

PS: I figured it out! I was using %= instead of =. Working example is here.

May I make an enhancement suggestion: would it make sense to update the documentation so that it clearly states that for "Auto-rule definitions," the attribute of p must (not should!) be compatible with the synthesized attribute of r, and that unlike for =, any semantic actions associated with p may not change the attribute type? (If that's correct?)

Kojoley commented 6 years ago

I figured it out! I was using %= instead of =

Glad you figured out the problem. I have spotted this, but the online compiler was killing itself with your example :smiley:.

May I make an enhancement suggestion

Yeah, go ahead, open a PR.