如何使用boost :: spirit解析数学表达式并将其绑定到函数

sro*_*ssi 3 c++ boost boost-bind boost-spirit boost-function

我想定义一个带有2个参数的函数

 double func(double t, double x); 
Run Code Online (Sandbox Code Playgroud)

从外部文本文件中读取实际实现的位置.
例如,在文本文件中指定

function = x*t;    
Run Code Online (Sandbox Code Playgroud)

功能应该实现的乘法xt,以便它可以在稍后阶段被调用.我正在尝试使用boost :: spirit来解析函数.但我不知道如何实现它.

下面,我创建了一个实现乘法的简单函数.我将它绑定到boost函数,我可以使用它.我还创建了一个简单的语法,它解析了两个双精度数之间的乘法.

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include "boost/function.hpp"
#include "boost/bind.hpp"
#include <boost/spirit/include/qi_symbols.hpp>
#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;
namespace ascii=boost::spirit::ascii;
using boost::spirit::ascii::space;
using boost::spirit::qi::symbols;

template< typename Iterator >
struct MyGrammar : public virtual qi::grammar<  Iterator,  ascii::space_type >
{
    MyGrammar() : MyGrammar::base_type(expression)
    {
        using qi::double_;
        //The expression should take x and t as symbolic expressions
        expression = (double_ >> '*' >> double_)[std::cout << "Parse multiplication: " << (qi::_1 * qi::_2)];
     }

     qi::rule<Iterator, ascii::space_type> expression;
 };

double func(const double a, const double b)
{
    return a*b; //This is the operation to perform
}

int main()
{
    typedef std::string::const_iterator iterator_Type;
    typedef MyGrammar<iterator_Type> grammar_Type;

    grammar_Type calc; 

    std::string str = "1.*2."; // This should be changed to x*t

    iterator_Type iter = str.begin();
    iterator_Type end = str.end();
    bool r = phrase_parse(iter, end, calc, space);

    typedef boost::function < double ( const double t,
                                       const double x) > function_Type;

    function_Type multiplication = boost::bind(&func, _1, _2);

    std::cout << "\nResult: " << multiplication( 2.0, 3.0) << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我修改上面的代码设置

std::string str = "x*t";
Run Code Online (Sandbox Code Playgroud)

我如何解析这样的表达式并将其绑定到函数,multiplication这样,如果我调用multiplication(1.0, 2.0)它,它将t与1.0,x关联到2.0并返回操作的结果?

seh*_*ehe 6

你将学习精神.大!

不过,你似乎咬得比你在这里咀嚼更多.

首先,你的语法实际上并没有解析表达式.它当然不会导致您可以绑定的函数.

  1. 实际上,您正在使用不产生任何结果的语法来解析输入.它只会产生一个副作用(即将简单的二进制表达式的结果与简单的操作数一起打印到控制台).这/ /类似/解释语言,虽然很快就会崩溃

    • 你尝试解析像这样的表达式 2*8 + 9
    • 你会输入回溯(哎呀,副作用已经开始)
  2. 接下来你是绑定func(顺便说一句是多余的;你没有绑定任何参数,所以你可以在function_Type multiplication(func);这里说),然后调用它.虽然很酷,但这与解析输入完全没有关系.

  3. 最后,你的问题是第三件事,在上面的任何地方都没有涉及到.这个问题是关于符号表和标识符查找.

    • 这意味着你应该解析实际标识符的来源(x或者t,例如)
    • 你需要将它们存储到符号表中,以便它们可以映射到一个值(也许是一个范围/生命周期)
    • 问题中存在一个空洞的逻辑漏洞,你没有定义"形式参数列表"的来源(你在这里的文字中提到它:function = x*t;但解析器没有处理它,你也没有硬编码任何这样的元数据); 所以我们甚至无法开始将事物xt事物映射到正式的参数列表(因为它不存在).

      让我们假设一下,实际上参数是位置的(就像它们一样,你似乎想要这个,因为你用位置参数调用绑定函数.)所以我们不必担心一个名字因为没有人会看到一个名字.)

    • 调用者应该在上下文中传递函数,以便在评估期间可以通过标识符名称查找值.

所以,虽然我可以试着让你坐下来,然后告诉你所有需要先创建的螺母和螺栓,然后你甚至可以梦想以你想要的方式将它粘合在一起,但不要.

这需要我太多时间,你可能会不堪重负.

建议

我只能建议查看更简单的资源.从教程开始

如果您在此过程中遇到任何问题,可以自由地询问您是否有被卡住的风险.但至少那时我们有一个可以回答的问题和真正帮助你的答案.

现在,看看我的其他一些答案,我实际上实现了这样的语法(有点按复杂程度排序):

这些答案中描述了每种方法的好处.这些解析器没有符号表,也没有评估上下文.

更多例子: