ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2019-08-24 21:04:45  阅读:251  来源: 互联网

标签:boost-bind c boost boost-spirit boost-function


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

 double func(double t, double x); 

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

function = x*t;    

该函数应该实现x和t之间的乘法,以便可以在稍后阶段调用它.
我正在尝试使用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;
}

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

std::string str = "x*t";

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

解决方法:

你将学习精神.大!

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

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

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

>你试图解析像2 * 8 9这样的表达式
>你会输入回溯(哎呀,副作用已经开始)

>接下来你是绑定func(顺便说一下这是多余的;你没有绑定任何参数,所以你可以只说function_Type multiplication(func); here),然后调用它.虽然很酷,但这与解析输入完全没有关系.
>最后,你的问题是第三件事,在上面的任何地方都没有涉及到.这个问题是关于符号表和标识符查找.

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

Let’s assume for the moment that in fact arguments are positional (as they are, and you seem to want this as you call the bound function with positional arguments anyways. (So we don’t have to worry about a name because no one will ever see a name.)

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

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

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

建议

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

>计算器系列教程很好.在这个答案中,我列出了计算器样本,并简要描述了他们演示的技术:What is the most efficient way to recalculate attributes of a Boost Spirit parse with a different symbol table?
>编译器教程实际上做了你想要的所有事情,但它们有点先进

Ask freely if you have any questions along the way and you’re at risk of getting stuck. But at least then we have a question that is answerable and answers that genuinely help you.

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

>比较好:这个Boost::spirit how to parse and call c++ function-like expressions的答案在运行中解释解析的表达式(这模仿了[std :: cout<<“Parse multiplication:”<<(qi :: _ 1 * qi: :_2)]在你自己的解析器中)
>那里的另一个答案(Boost::spirit how to parse and call c++ function-like expressions)实现了目标,但使用了专用的AST表示和单独的解释阶段.

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

更多例子:

>一个简单的布尔表达式语法评估器(仅支持文字,而不支持变量)
> Building a Custom Expression Tree in Spirit:Qi (Without Utree or Boost::Variant)

标签:boost-bind,c,boost,boost-spirit,boost-function
来源: https://codeday.me/bug/20190824/1711925.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有