I want to use a function in the semantic action of boot::spirit

Asked 2 years ago, Updated 2 years ago, 82 views

I am currently using boost::spirit to create a function calculator.

The four operations can be implemented as follows:

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

For functions, for example, considering a function that calculates the mean of two numbers,

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

Is it possible to make it look like this?

c++ boost

2022-09-30 19:54

2 Answers

How about writing Boost.Lambda or C++ lambda expressions within the semantic action []?

The first example is using Boost.Lambda.

#include<iostream>
# include <string>

# include <boot/fusion/sequence/intrinsic/at_c.hpp>
# include<boot/lambda/lambda.hpp>
# include<boot/lambda/bind.hpp>
# include<boot/spirit/include/qi_parse.hpp>
# include<boot/spirit/include/qi_real.hpp>
# include<boot/spirit/include/qi_action.hpp>
# include<boot/spirit/include/qi_char_.hpp>
# include<boot/spirit/include/qi_sequence.hpp>

using namespace boot::spirit::qi;

namespace bll=boot::lambda;

double Average (const boot::fusion::vector<double, double>&x)
{
    return(boot::fusion::at_c<0>(x)+boot::fusion::at_c<1>(x))*0.5;
}

int main()
{
    std::string = "1,2";
    auto first=s.begin();
    double val;
    pool success=parse(
        first,
        s.end(),
        (double_>>', '>> double_) [bll::var(val) = bll::bind(Average, bll::_1)]
    );
    if(success)
    {
        std::cout<<val<<std::endl;
    }
}

This is an example of using the lambda formula.

#include<iostream>
# include <string>

# include <boot/fusion/sequence/intrinsic/at_c.hpp>
# include<boot/spirit/include/qi_parse.hpp>
# include<boot/spirit/include/qi_real.hpp>
# include<boot/spirit/include/qi_action.hpp>
# include<boot/spirit/include/qi_char_.hpp>
# include<boot/spirit/include/qi_sequence.hpp>

using namespace boot::spirit::qi;

namespace bll=boot::lambda;

double Average (const boot::fusion::vector<double, double>&x)
{
    return(boot::fusion::at_c<0>(x)+boot::fusion::at_c<1>(x))*0.5;
}

int main()
{
    std::string = "1,2";
    auto first=s.begin();
    double val;
    pool success=parse(
        first,
        s.end(),
        (double_>', '>> double_) [[&(const auto&x) {val=Average(x);}]
    );
    if(success)
    {
        std::cout<<val<<std::endl;
    }
}


2022-09-30 19:54

If you want to use normal function notation, BOOST_PHOENIX_ADAPT_FUNCTION will convert it into a form that can be used within semantic actions.

#include<iostream>
# include <string>
# include<boot/spirit/include/qi.hpp>
# include<boot/spirit/include/phoenix.hpp>

using namespace boot::spirit::qi;
using namespace boot::phoenix;

BOOST_PHOENIX_ADAPT_FUNCTION(double, Average, [ ] (double1, double2) {return(d1+d2)*0.5; }, 2)

int main()
{
    std::string = "1,2";
    auto first=s.begin();
    double val;
    pool success=parse(
        first,
        s.end(),
        (double_>>', '>>double_) [ref(val)=Average(_1,_2)]
    );
    if(success)
    {
        std::cout<<val<<std::endl;
    }
}

If you don't want to convert a normal function, you can use bind.

#include<iostream>
# include <string>
# include<boot/spirit/include/qi.hpp>
# include<boot/spirit/include/phoenix.hpp>

using namespace boot::spirit::qi;
using namespace boot::phoenix;

double Average (double1, double2)
{
    return(d1+d2)*0.5;
}

int main()
{
    std::string = "1,2";
    auto first=s.begin();
    double val;
    pool success=parse(
        first,
        s.end(),
        (double_>>', '>>double_) [ref(val)=bind(Average,_1,_2)]
    );
    if(success)
    {
        std::cout<<val<<std::endl;
    }
}


2022-09-30 19:54

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.