parsing - 运算符优先级:为什么要以这种方式解析一元运算符?
问题描述
我正在关注 Bob Nystrom 的好书“Crafting Interpreters”。
如果这个问题对于这个网站来说太具体了,请告诉我 - 我已经尝试了几个小时,但我自己无法解决这个问题:)
在编译表达式一章中,在函数unary()
中,函数parsePrecedence(Precedence)
被调用PREC_UNARY
而不是PREC_UNARY + 1
。
这本书解释说这是为了启用一元运算符的“嵌套”。例如:--1
。
但是,在parsePrecedence(Precedence)
解析前缀运算符之前不检查优先级 - 仅在中缀运算符之前检查。并且unary
是前缀解析器。
所以传递PREC_UNARY
或PREC_UNARY + 1
传递parsePrecedence(Precedence)
似乎没有什么区别。我错过了什么?
解决方案
简单的答案是您是对的:对于这种特定的语法,没有区别,因为没有二元(或后缀)运算符具有优先级PREC_UNARY
,并且将使用的测试是 ≤。
尽管如此,传统的答案是使用PREC_UNARY
,因为一元前缀运算符(必然)是右结合的。此约定来自二元运算符的情况,您需要将运算符的优先级加一用于左关联运算符(正常情况),并将运算符的优先级本身用于右关联运算符(例如求幂和赋值)。(分配实际上要复杂一些,但我个人认为 Bob Nystrom 提出的解决方案比必要的要复杂得多。)
另一个传统的答案来自使用自下而上的运算符优先级解析器(Dijkstra 的“分流场”)而不是自上而下的 Pratt 解析器的可能性。充分探索自下而上的解析远远超出了这个问题的范围;只要说同样的原则适用于关联性就足够了。
推荐阅读
- python - 创建一个空的 DataFrame 作为默认参数
- c++ - 媒体基金会:WavSink 以比实时消耗速率更快的速度假脱机 - 假脱机可以被实时限制吗?
- ios - 原因:“杀死应用程序,因为它在收到 PushKit VoIP 推送回调后从未向系统发布来电。”
- python - 检查元素,如果至少 3 个匹配,则为 True
- android - 需要更多详细信息来自动化 Kiosk 模式 android 应用程序
- elixir - Elixir:将符号转换为函数
- postgresql - 如何在公共 IP 上运行 POSTGRESQL 服务器
- c++ - 是什么阻止 STL 拥有“std::deep_ptr”?
- jasper-reports - JasperReports:更新“主”报告时更新几个“从属”报告
- algorithm - 如何理解蒙特卡洛树搜索的 4 个步骤