Ruby 中的运算符和方法
大多数看起来像运算符的东西都是 Ruby 中的方法; 1 + 2
是 1.+(2)
的语法糖。
尽管 +
和 *
是程序可以重新定义的方法,但 Ruby 具有特殊的魔力,可以将 1 + 2 * 3
计算为 1 .+(2.*(3))
而不是 1.+(2).*(3)
。
我想知道 Ruby 中这种特殊的魔力在哪里——如果它被硬连接到解释器中的话。
阿里。
Most things that look like operators are methods in Ruby; 1 + 2
is syntactic sugar for 1.+(2)
.
Even though +
and *
are methods that a program can redefine, Ruby has special magic to evaluate 1 + 2 * 3
as 1.+(2.*(3))
instead of 1.+(2).*(3)
.
I wonder where this special magic lives in Ruby--if it is hard-wired into the interpreter.
Ari.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在所有 Ruby 实现中,运算符优先级由解析器处理。由于几乎所有现有的 Ruby 实现都使用相同的解析器,或者从相同的 YACC 语法生成的解析器,
parse.y
是您要查看的文件。 (例如,在 JRuby 中,该文件本质上是相同的:src/org/jruby/parser/Ruby19Parser.y
。IronRuby 相同:Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/ Parser.y
。)仅有的四个不直接使用 YARV 解析器或使用从 YARV 的
parse.y< 生成的 YACC 克隆解析器的 Ruby 实现/code> 是 Cardinal、tinyrb、RubyGoLightly 和 XRuby。
Cardinal 是 Parrot 虚拟机的 Ruby 实现,由于 Parrot 包含 Parrot 语法引擎,Cardinal 自然会使用它。有趣的文件是
src/parser/语法.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 使用 Melbourne 解析器,它本质上是打包为 C 扩展的 YARV 解析器。 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 语法来查找模块、类和方法、注释以及提取方法参数列表。它们不处理运算符优先级。
In all Ruby Implementations, Operator Precedence is handled by the parser. Since pretty much all existing Ruby Implementations use the same parser, or a parser generated from the same YACC grammar,
parse.y
in YARV is the file you want to look at. (In JRuby, for example, that file is essentially the same:src/org/jruby/parser/Ruby19Parser.y
. Same for IronRuby:Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.y
.)The only four Ruby Implementations that do not either use the YARV parser directly or use a YACC clone generated parser from YARV's
parse.y
, are Cardinal, tinyrb, RubyGoLightly and XRuby.Cardinal is a Ruby implementation for the Parrot virtual machine, and since Parrot includes the Parrot Grammar Engine, Cardinal naturally uses that. The interesting file is
src/parser/grammar.pg
. PGE is a hybrid recursive-descent parser/operator precedence parser, which means that operator precedence shows up pretty nicely in the grammar file.Tinyrb uses a PEG parser utilizing Ian Piumarta's leg library. As is typical for PEG parsers, there is no operator precedence table, rather the precedence is implicit in the hierarchical structure of the grammar. See
vm/grammar.leg
for details. RubyGoLightly is derived from tinyrb, except it uses Go instead of C as the implementation language, but it uses the same PEG grammar.XRuby uses ANTLR for its parser. Here, the interesting file is
src/com/xruby/compiler/parser/ruby.g
.Rubinius uses the Melbourne parser, which is essentially YARV's parser packaged as a C extension. MagLev uses
ruby_parser
(see below).Apart from the Ruby Implementations, there are also other Ruby parsers available.
Ryan Davis's ruby_parser is derived from the YARV YACC grammar. It uses racc as the parser generator. See
lib/ruby_parser.y
.Caleb Clausen's RedParse uses Caleb's own hand-written compiler-interpreter. The interesting file is
lib/redparse/babyparser.rb
.That's all the parsers I know, that actually handle operator precedence. There is another parser built into RDoc, and there used to be one in YARD (it now uses RedParse), but those only handle just enough of Ruby's syntax to find modules, classes and methods, comments and extract method parameter lists. They don't deal with operator precedence.
语言文档中的“运算符表达式”给出了包含可以作为方法重写的运算符的表。您无法编写自己的运算符 - 运算符与其符号名称的映射位于解析器内部。
"Operator Expressions" in the language documentation gives a table with the operators that can be overridden as methods. You can't make up your own operators — the mapping of operators to their symbol names lives inside the parser.
是的,它是硬连线的,因此您无法添加新运算符或更改现有运算符的优先级。
Yes, it's hardwired, so you can't add new operators or change the precedence of existing operators.