1

我正在为类似 javascript 的语言编写一个编译器来取乐。又名我正在学习轮子,所以我为自己制作了一个并试图找出所有内容,但现在我被卡住了。

我知道在解析简单的中缀表达式时,调车场算法是一个不错的算法。我能够弄清楚如何为前缀和后缀运算符扩展该算法,并且还能够解析简单的函数。

例如:2+3*a(3,5)+b(3,5)变成2 3 <G> 3 5 a () * + <G> 3 5 b () +

<G>是一个推入堆栈的保护令牌,它将存储返回地址等。()是调用堆栈顶部的函数的调用命令,该函数弹出必要数量的参数并在返回时推回结果。)

如果函数名只是一个标记,我可以简单地将其标记为函数符号,如果直接后跟一个括号。在此过程中,如果我遇到一个函数符号,我会将其压入操作符堆栈,并在完成参数转换后将其弹出。

到目前为止,这是有效的。

但是,如果我添加具有成员函数的选项,则.运算符。事情变得更加棘手。例如,我想将a.b.c(12)+d.e.f(34)I can't mark c 和 f 转换为函数,因为a.b.cd.e.f是函数。如果我在这样的表达式上启动解析器,结果将a b . <G> 12 c () . d e . <G> 34 f () .是显然是错误的。我希望它是<G> 12 a b . c . () <G> 34 d e . f. ()正确的。但是如果我添加一些括号,我可以让事情变得更复杂:(a.b.c)()。或者我创建一个函数,该函数返回一个我再次调用的函数:f(a,b)(c,d).

有没有简单的方法来处理这些棘手的情况?

4

2 回答 2

0

(I saw this question is still alive. I found the solution for it myself.)

First I threat the (...) and [...] expressions as one token and expand them (recursively) when needed. Then I detect the function calls and array subscripts. If there isn't an infix operator before a parenthesized token, then that's a function call or an array subscript, so I insert a special call-function or access operator there. With this modification it works like charm.

于 2011-03-05T12:06:46.457 回答
0

您的方法的一个问题是您将 object 及其成员视为两个单独的标记,由.. 经典的Shunting yard算法对OOP一无所知,并且依赖于单个令牌进行函数调用。所以解决问题的第一种方法是使用一个标记来调用对象成员——即整个a.b.c必须是一个标记。

您也可以参考自动解析器生成器来解决您的问题。它们允许将目标语言 (JavaScript) 的完整语法定义为一组正式规则并自动生成解析器。流行工具列表包括在不同编程语言上生成解析器的工具:ANTLR、Bison + Lex、Lemon + Ragel


--artem

于 2011-01-14T13:55:08.530 回答