首页 > 解决方案 > 运算符优先级:为什么要以这种方式解析一元运算符?

问题描述

我正在关注 Bob Nystrom 的好书“Crafting Interpreters”。

如果这个问题对于这个网站来说太具体了,请告诉我 - 我已经尝试了几个小时,但我自己无法解决这个问题:)

在编译表达式一章中,在函数unary()中,函数parsePrecedence(Precedence)被调用PREC_UNARY而不是PREC_UNARY + 1

这本书解释说这是为了启用一元运算符的“嵌套”。例如:--1

但是,在parsePrecedence(Precedence)解析前缀运算符之前不检查优先级 - 仅在中运算符之前检查。并且unary是前缀解析器。

所以传递PREC_UNARYPREC_UNARY + 1传递parsePrecedence(Precedence)似乎没有什么区别。我错过了什么?

标签: parsingcompiler-construction

解决方案


简单的答案是您是对的:对于这种特定的语法,没有区别,因为没有二元(或后缀)运算符具有优先级PREC_UNARY,并且将使用的测试是 ≤。

尽管如此,传统的答案是使用PREC_UNARY,因为一元前缀运算符(必然)是右结合的。此约定来自二元运算符的情况,您需要将运算符的优先级加一用于左关联运算符(正常情况),并将运算符的优先级本身用于右关联运算符(例如求幂和赋值)。(分配实际上要复杂一些,但我个人认为 Bob Nystrom 提出的解决方案比必要的要复杂得多。)

另一个传统的答案来自使用自下而上的运算符优先级解析器(Dijkstra 的“分流场”)而不是自上而下的 Pratt 解析器的可能性。充分探索自下而上的解析远远超出了这个问题的范围;只要说同样的原则适用于关联性就足够了。


推荐阅读