数学表达式的自定义解释器

时间:2011-07-15 22:51:08

标签: c++ c parsing interpreter

我必须评估包含变量的大量表达式,我正在考虑编写一个小的自定义解释器来保持编译的快速和小。但是我没有这方面的经验,也有一些问题。

假设我们有一个包含数学表达式和一组有限对象的文件。该文件可能如下所示:

expr[x,y,z] = 2*x*y + x^2 + 28/14*z*(x*y^2 + 15*z) + ...

我想以某种方式解析它,以便我可以在我的应用程序中以数字方式评估表达式 只需调用函数expr(float x, float y, float z)即可。参数的数量不应该是固定的(编辑:每个表达式都有自己的定义和适当数量的参数或接受一个数组)并且应该允许嵌套括号以保持输入文件相当小。

由于表达式都是多项式类型,我可以想一想数据结构应该是什么样子,但解析看起来很困难。我已经在SO上找到了一些类似问题的答案,例如使用Lua。

然而,最大的问题是,与直接从自动生成的C代码中编译这些表达式相比,创建和调用这些对象时的性能损失是什么。

提前致谢!

编辑:请仅考虑上述expr()的示例。我想最好的方法是让模板类的对象保存稀疏数组中变量的系数和幂。

3 个答案:

答案 0 :(得分:6)

性能是一个长篇字符串问题。解释语言几乎总是比编译的C代码慢,以评估算术表达式。但并不是很多程序花费大部分时间进行算术运算,所以大部分时间都无关紧要。无论是在每次评估表达式时解析表达式还是(从你说的内容看起来更可能),它都会产生影响,并将其解析为某种中间形式。

你不可能从你说的内容,是否对你来说是否重要,或者你会写一个翻译的速度有多快,但我不会指望它会比花费的时间慢10倍。评估表达方式。首次尝试解释的情况要差得多。

至于那个中间形式 - 通常的起点是使用Dijkstra的“shunting-yard”算法将你的中缀表达式转换为反向波兰语形式。这给你一系列“符号”,“字节代码”,调用它们你喜欢的东西,并且很容易为该表单编写表达式求值器 - 每个运算符只是从堆栈中弹出其操作数,执行操作,然后推送结果到堆栈,直到表达式的最终值是结尾处唯一的结果。数字文字和变量名称就像没有弹出操作数的“运算符”,并推动它们的价值。

[编辑 - 取决于您的用户是谁,您的程序可能可以获取该文本文件,从中生成C程序,运行编译器然后运行生成的程序(或者打开并调用生成的程序) DLL)。显然,它依赖于许多系统特定的东西(一个编译器正在安装),并且需要对表达式进行足够的评估,以便克服编译开销。]

答案 1 :(得分:1)

你说这个问题是“大复杂表达”,你担心性能损失。那么你应该考虑编译它们,而不是解释它们。 (良好的解释器比编译代码慢10倍作为经验法则;糟糕/临时解释器往往会更糟糕)。

通常的做法是以某种方式“编译”表达式,包括构建解析器,代码生成器,优化等。

C编译器已经完成了这一切。所以我认为 将这些表达式翻译成C语言会好得多。 然后编译它们很容易,并且与您希望作为解释器所做的任何事情相比,执行将是闪电般快速的。这也可以做到 使用解析器和更简单的语法指导翻译。

但是如果这些表达式都是由Mathematica生成的,那么它们将具有相当标准但不复杂的结构。在这种情况下,我猜你可以编写一个基于正则表达式的翻译器,可以将Mathematica表单映射到C函数,而不会有太多麻烦; Perl对此非常理想。这为您提供了易于实施且非常快速的解决方案。

对于它的价值,我相信Mathematica可以选择将Mathematica表达式直接转换为C.似乎也值得一试。

答案 2 :(得分:0)

Bison Manual中有一个简单的例子。