我正在为类似 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.c
和d.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)
.
有没有简单的方法来处理这些棘手的情况?