如何使用boost :: spirit解析数学表达式并将其绑定到函数 [英] How to parse a mathematical expression with boost::spirit and bind it to a function

查看:110
本文介绍了如何使用boost :: spirit解析数学表达式并将其绑定到函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to define a function taking 2 arguments

 double func(double t, double x); 

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

where the actual implementation is read from an external text file.
For example, specifying in the text file

function = x*t;    

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

the function should implement the multiplication between x and t, so that it could be called at a later stage. I'm trying to parse the function using boost::spirit. But I do not know how to actually achieve it.

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

Below, I created a simple function that implements the multiplication. I bind it to a boost function and I can use it. I also created a simple grammar, which parse the multiplication between two doubles.

#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;
}

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

If I modify the above code setting

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

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

how can I parse such an expression and bind it to the function multiplication such that, if I call multiplication(1.0, 2.0), it associates t to 1.0, x to 2.0 and it returns the result of the operation?

推荐答案

您将学习Spirit.太好了!

You're going to learn Spirit. Great!

不过,似乎您在这里所咬的东西超出了您的咀嚼能力.

It seems you're biting off more than you can chew here, though.

首先,您的语法实际上尚未解析表达式.当然,它不会导致您可以绑定的功能.

Firstly, your grammar doesn't actually parse an expression yet. And it certainly doesn't result in a function that you can then bind.

  1. 实际上,您正在使用不产生任何结果的语法来解析输入.它只会创建一个副作用(将带有直接简单操作数的简单二进制表达式的结果打印到控制台).这种/relikes/解释性语言,尽管

  1. In fact you're parsing the input using a grammar that is not producing any result. It only creates a side-effect (which is to print the result of the simple binary expression with immediate simple operands to the console). This /resembles/ interpreted languages, although it would soon break up when

  • 您尝试解析类似2*8 + 9
  • 的表达式
  • 您将输入回溯的信息(糟糕,副作用已经触发)
  • you try to parse an expression like 2*8 + 9
  • you would have input that backtracks (oops, the side effect already fired)

接下来,您将绑定func(顺便说一句,这是多余的;您没有绑定任何参数,因此您只能在此处说function_Type multiplication(func);)并调用它.虽然很酷,但实际上与解析输入无关.

Next up you're binding func (which is redundant by the way; you're not binding any arguments so you could just say function_Type multiplication(func); here), and calling it. While cool, this has literally nothing to do with the parsing input.

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

Finally, your question is about a third thing, that wasn't even touched upon anywhere in the above. This question is about symbol tables and identifier lookup.

  • 这意味着您应该解析源以获取实际的标识符(例如xt)
  • 您需要将它们存储到符号表中,以便可以将它们映射到一个值(也许是作用域/生命周期)
  • 问题中存在一个逻辑漏洞,您无需定义形式参数列表"的来源(您在此处的文本中提到了它: function = x*t; 解析器不处理它,您也没有对任何此类元数据进行硬编码);因此我们甚至无法开始将xt映射到正式参数列表(因为它不存在).

  • This would imply you should parse the source for actual identifiers (x or t, e.g.)
  • you'd need to store these into a symbol table so they could be mapped to a value (and perhaps a scope/lifetime)
  • There is a gaping logic hole in the question where you don't define the source of the "formal parameter list" (you mention it in the text here: function = x*t; but the parser doesn't deal with it, neither did you hardcode any such metadata); so there is no way we could even start to map the x and t things to the formal argument list (because it doesn't exist).

让我们暂时假设事实上参数是位置参数(按原样,并且在使用位置参数调用绑定函数时,您似乎想要这么做.(因此,我们不必担心名称,因为没人会看到名称.)

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

  • the caller should pass in a context to the functions, so that values can be looked up by identifier name during evaluation.

    因此,尽管我可以尝试让您坐下来,与您讨论所有首先需要创建的细节,然后您甚至可以梦想以自己想要的奇妙方式将它们粘合在一起,但不要这样.

    So, while I could try to sit you down and talk you through all the nuts and bolts that need to be created first before you can even dream of glueing it together in fantastic ways like you are asking for, let's not.

    这将花费我太多时间,并且您可能不知所措.

    It would take me too much time and you would likely be overwhelmed.

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

    I can only suggest to look at simpler resources. Start with the tutorials

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆