【问题标题】:How to convert method calls to postfix notation?如何将方法调用转换为后缀表示法?
【发布时间】:2010-12-11 19:39:38
【问题描述】:

我正在为类似 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) 我不能将 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)

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

【问题讨论】:

    标签: parsing compiler-construction expression postfix-notation


    【解决方案1】:

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

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


    --artem

    【讨论】:

    • .+ 一样是一个运算符。
    • @delnan 是对的。我们应该像对待普通运算符一样对待 dot。
    【解决方案2】:

    (我看到这个问题还活着。我自己找到了解决方案。)

    首先我威胁(...)[...] 表达式作为一个标记,并在需要时(递归地)扩展它们。然后我检测函数调用和数组下标。如果带括号的标记之前没有中缀运算符,那么这是一个函数调用或数组下标,所以我在那里插入一个特殊的调用函数或访问运算符。有了这个修改,它就像魅力一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-27
      • 2015-02-15
      • 1970-01-01
      • 2014-08-26
      • 1970-01-01
      • 2014-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多