Building a qi :: rule with a function attribute

I am trying to create a rule that returns function<char(char const *)>

, created by currying a Phoenix expression. For example.

start = int_[_val = xxx];
rule<Iterator, function<char(char const *)> start;

      

What should it xxx

be so that parsing the string "5"

should give me a function that gives me the fifth character of its input? I've tried things like lambda(_a = arg1)[arg1[_a]](_1)

but I haven't been able to pounce on the magic formula.

In other words, I need the curry attribute arg2[arg1]

on the parse int value

Very grateful for any suggestions. Note that I am on VC2008, so C ++ 11 lambdas is not available.

Mike

+2


source to share


1 answer


After committing this rule declaration:

typedef boost::function<char(char const*)> Func;
qi::rule<Iterator, Func()> start;

      

it worked: Live On Coliru (C ++ 03).

UPDATE

Why did I get such a complicated fixture?

qi::_val = px::bind(px::lambda[arg1[arg2]], px::lambda[arg1], qi::_1)

      

Well. Let me tell you about the joy of complexing functional composition with lazy evaluation (in C ++ template meta-programming, which has these surprises with reference / value semantics): Don't do the following:

qi::_val = px::lambda(_a = qi::_1) [arg1[_a]] // UB!!! DON'T DO THIS

      

Depending on the compiler, optimization level, it might look like * . But it calls Undefined Behavior [1] . The problem is what will be stored as a reference to the attribute exposed by the parser expression . However, this link after the completion of the parsing context is a deception link. qi::_1

qi::int_

So, evaluating indirect functions through an invalid reference. To avoid this, you must say ( Live On Coliru ):

qi::_val = px::lambda(_a = px::val(qi::_1)) [arg1[_a]]

      



or even (if you like obscure code):

qi::_val = px::lambda(_a = +qi::_1) [arg1[_a]]

      

Or, you know, you can stick with the bound nested lambda, since the default binding is semantics-for qi::_1

(if you didn't use the phx::cref

/ wrappers phx::ref

).

Hope the above analysis has brought home what I did in the comments before:

Please note that I would not recommend this style of code. Programming of a higher order with Phoenix is difficult enough without having made them out of lazy participants in some built-in the DSL-template template: qi::_val = px::bind(px::lambda[arg1[arg2]], px::lambda[arg1], qi::_1)

. 'Nuff said ?


#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/function.hpp>

namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;

typedef boost::function<char(char const*)> Func;

int main()
{
    typedef std::string::const_iterator Iterator;
    using namespace boost::phoenix::arg_names;

    qi::rule<Iterator, Func()> start;

    start = qi::int_ 
            [ qi::_val = px::bind(px::lambda[arg1[arg2]], px::lambda[arg1], qi::_1) ];
    // or:  [ qi::_val = px::lambda(_a = px::val(qi::_1))[arg1[_a]] ];

    static char const* inputs[] = { "0", "1", "2", "3", "4", 0 };

    for (char const* const* it = inputs; *it; ++it)
    {
        std::string const input(*it);
        Iterator f(input.begin()), l(input.end());

        Func function;
        bool ok = qi::parse(f, l, start, function);

        if (ok)
            std::cout << "Parse resulted in function() -> character " 
               << function("Hello") << "; " 
               << function("World") << "\n";
        else
            std::cout << "Parse failed\n";

        if (f != l)
            std::cout << "Remaining unparsed: '" << std::string(f, l) << "'\n";
    }
}

      

Printing

Parse resulted in function() -> character H; W
Parse resulted in function() -> character e; o
Parse resulted in function() -> character l; r
Parse resulted in function() -> character l; l
Parse resulted in function() -> character o; d

      


[1] (MSVC2013 crashed, gcc might run in -O3, but segfaults in -O0, etc.)

+2


source







All Articles