在运行时从 RPN 构造函数可调用对象

Construct a function-callable object from an RPN at a runtime

我正在设计一个程序,可以对流数据执行某些操作。 操作由运行时提供的 RPN(逆向抛光表示法)表达式定义。数据从文件源流式传输,一次一个固定大小的部分。操作引用了一些当前输入的数据部分,例如 data[1]。该程序对所有输入部分应用相同的操作(并流出结果)。

实现一个对数字和算术运算给出结果的RPN解析器是很容易的。然而,使用这样的实现意味着为每个数据部分重新解析 RPN。

我想实现的是以某种方式构建一个对象,该对象将根据数据的基本操作字母表保存曾经解析过的 RPN 实现,程序将在其中提供输入数据(或填写输入), 调用对象的operator()获取并输出结果

如何使用 'non-modern' C++(没有 C++11C++14 实现这样的 class(callable expression)并构造这样的对象)?

自其 RPN 以来,操作可以建模为堆栈的一系列转换。将一个输入部分加载到堆栈上,然后按顺序执行您的操作就可以解决问题。不需要树,它隐含在操作顺序中。也不需要重新解析,它确实是一系列操作(函数或仿函数)而不是一系列表示操作的符号。

我会选择仿函数,因为我更喜欢存储对象的引用或指针,而不是存储函数的引用或指针。您将其实现为具有重载运算符 () 的 class 来执行所需的堆栈转换(例如,如果它是乘法函子,则将两个顶部元素相乘)。

上图:古代设备以这种方式工作...

关于堆栈中存储的内容和不存储的内容:

  • 首先,您的操作数存储在与输入顺序匹配的队列中
  • 您的运算符对象,解析一次且永远不会改变的结果,单独存储在运算符队列中。
  • 应用'get'运算符会将一个操作数从队列转移到操作数栈

例如如果你想计算

sin (3 + 4) / (5 + 6)

您的操作数队列是:

[start] 3 4 5 6 [end]

您的运算符对象队列(它包含指向函子的指针,而不是符号,每个函子只有一个实例,但可能被多次引用)是:

[start] &getFunctor &getFunctor &addFunctor &sinFunctor &getFunctor &getFunctor &addFunctor &divideFunctor [begin]

您的操作数堆栈开始时是空的:

[top][bottom]

应用操作员队列随后会给你:

(get)    [top] 3 [bottom]
(get)    [top] 3 4 [bottom]
(add)    [top] 7 [bottom]
(sin)    [top] 0.657 [bottom]
(get)    [top] 5  0.657 [bottom]
(get)    [top] 5 6  0.657 [bottom]
(add)    [top] 11  0.657[bottom]
(divide) [top] 0.0597 [bottom]

如果您随后想对例如

应用完全相同的操作
[start]10 20 30 40[end]

只需替换操作数队列(或者让您的操作数队列的起始指针指向您的操作数文件的下一个 "chunk",然后再次 运行 您的操作员队列针对这个新的操作数序列.

请注意,如上所述,运算符队列不包含运算符符号,而是指向准备就绪的函数对象的指针,这些函数对象将在您调用它们时立即执行它们的操作,而无需重新解析或重新生成代码。

因此,如果您有大量数据:

[start of file]3 4 5 6   10 20 30 40   -1 -10 15 80 ...[end of file]

您只需继续应用相同的操作员队列,一切都会正常进行。