boost::spiritのセマンティックアクションで関数を使いたい


現在 boost::spirit を使って関数電卓を作っています。

四則演算は次のような感じで実装できますが、

`(double_>>'+'>>double_)[_val=_1+_2]`

関数の場合、例えば二つの数の平均を計算する関数などを考えたとき、

`(double_>>','>>double_)[_val=Average(_1,_2)]`

という感じにすることはできますか？




セマンティックアクション`[]`の中に、Boost.LambdaやC++ラムダ式を書く方法はどうでしょうか。

まずはBoost.Lambdaを使う例です。

[code]

    #include <iostream>
    #include <string>
    
    #include <boost/fusion/sequence/intrinsic/at_c.hpp>
    #include <boost/lambda/lambda.hpp>
    #include <boost/lambda/bind.hpp>
    #include <boost/spirit/include/qi_parse.hpp>
    #include <boost/spirit/include/qi_real.hpp>
    #include <boost/spirit/include/qi_action.hpp>
    #include <boost/spirit/include/qi_char_.hpp>
    #include <boost/spirit/include/qi_sequence.hpp>
    
    using namespace boost::spirit::qi;
    
    namespace bll = boost::lambda;
    
    double Average(const boost::fusion::vector<double, double>& x)
    {
        return (boost::fusion::at_c<0>(x) + boost::fusion::at_c<1>(x)) * 0.5;
    }
    
    int main()
    {
        std::string s = "1,2";
        auto first = s.begin();
        double val;
        bool success = parse(
            first,
            s.end(),
            (double_ >> ',' >> double_)[bll::var(val) = bll::bind(Average, bll::_1)]
        );
        if (success)
        {
            std::cout << val << std::endl;
        }
    }
    
[/code]

こっちはラムダ式を使う例です。

[code]

    #include <iostream>
    #include <string>
    
    #include <boost/fusion/sequence/intrinsic/at_c.hpp>
    #include <boost/spirit/include/qi_parse.hpp>
    #include <boost/spirit/include/qi_real.hpp>
    #include <boost/spirit/include/qi_action.hpp>
    #include <boost/spirit/include/qi_char_.hpp>
    #include <boost/spirit/include/qi_sequence.hpp>
    
    using namespace boost::spirit::qi;
    
    namespace bll = boost::lambda;
    
    double Average(const boost::fusion::vector<double, double>& x)
    {
        return (boost::fusion::at_c<0>(x) + boost::fusion::at_c<1>(x)) * 0.5;
    }
    
    int main()
    {
        std::string s = "1,2";
        auto first = s.begin();
        double val;
        bool success = parse(
            first,
            s.end(),
            (double_ >> ',' >> double_)[([&](const auto& x) {val = Average(x);})]
        );
        if (success)
        {
            std::cout << val << std::endl;
        }
    }
    
[/code]

