大多数看起来像运算符的东西都是 Ruby 中的方法。1 + 2
是 . 的语法糖1.+(2)
。
尽管+
和*
是程序可以重新定义的方法,但 Ruby 具有特殊的魔法来评估1 + 2 * 3
as1.+(2.*(3))
而不是1.+(2).*(3)
.
我想知道这种特殊的魔法在 Ruby 中的什么地方——如果它被硬连接到解释器中。
阿里。
大多数看起来像运算符的东西都是 Ruby 中的方法。1 + 2
是 . 的语法糖1.+(2)
。
尽管+
和*
是程序可以重新定义的方法,但 Ruby 具有特殊的魔法来评估1 + 2 * 3
as1.+(2.*(3))
而不是1.+(2).*(3)
.
我想知道这种特殊的魔法在 Ruby 中的什么地方——如果它被硬连接到解释器中。
阿里。
在所有 Ruby 实现中,运算符优先级由解析器处理。由于几乎所有现有的 Ruby 实现都使用相同的解析器,或者从相同的 YACC 语法生成的解析器,因此parse.y
在 YARV 中是您想要查看的文件。(例如,在 JRuby 中,该文件本质上是相同的:src/org/jruby/parser/Ruby19Parser.y
. IronRuby 相同:Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.y
。)
仅有的四个不直接使用 YARV 解析器或使用从 YARV 克隆生成的解析器的Ruby 实现parse.y
是 Cardinal、tinyrb、RubyGoLightly 和 XRuby。
Cardinal 是 Parrot 虚拟机的 Ruby 实现,由于 Parrot 包含 Parrot 语法引擎,Cardinal 自然使用它。有趣的文件是src/parser/grammar.pg
. PGE 是一种混合递归下降解析器/运算符优先级解析器,这意味着运算符优先级在语法文件中显示得非常好。
Tinyrb 使用一个利用 Ian Piumarta 的 leg 库的 PEG 解析器。与 PEG 解析器一样,没有运算符优先级表,优先级隐含在语法的层次结构中。详情请参阅vm/grammar.leg
。RubyGoLightly 是从 tinyrb 派生的,只是它使用 Go 而不是 C 作为实现语言,但它使用相同的 PEG 语法。
XRuby 使用 ANTLR 作为其解析器。在这里,有趣的文件是src/com/xruby/compiler/parser/ruby.g
.
Rubinius 使用墨尔本解析器,它本质上是 YARV 的解析器,打包为 C 扩展。MagLev 使用ruby_parser
(见下文)。
除了 Ruby 实现之外,还有其他可用的 Ruby 解析器。
Ryan Davis 的 ruby_parser 源自 YARV YACC 语法。它使用 racc 作为解析器生成器。见lib/ruby_parser.y
。
Caleb Clausen 的 RedParse 使用 Caleb 自己的手写编译器解释器。有趣的文件是lib/redparse/babyparser.rb
.
这就是我所知道的所有解析器,它们实际上处理运算符优先级。RDoc 中内置了另一个解析器,以前在 YARD 中也有一个(它现在使用 RedParse),但这些解析器仅处理 Ruby 的语法,以查找模块、类和方法、注释和提取方法参数列表。他们不处理运算符优先级。
语言文档中的“运算符表达式”提供了一个表格,其中包含可以作为方法覆盖的运算符。你不能组成自己的运算符——运算符到它们的符号名称的映射存在于解析器中。
是的,它是硬连线的,因此您不能添加新的运算符或更改现有运算符的优先级。