演算子のように見えるもののほとんどは、Ruby ではメソッドです。1 + 2
のシンタックス シュガーです1.+(2)
。
+
とはプログラムで再定義できるメソッドですが、Ruby にはの代わりにとして*
評価する特別な魔法があります。1 + 2 * 3
1.+(2.*(3))
1.+(2).*(3)
この特別な魔法が Ruby のどこに存在するのか疑問に思います。それがインタープリターに組み込まれているとしたら。
アリ。
演算子のように見えるもののほとんどは、Ruby ではメソッドです。1 + 2
のシンタックス シュガーです1.+(2)
。
+
とはプログラムで再定義できるメソッドですが、Ruby にはの代わりにとして*
評価する特別な魔法があります。1 + 2 * 3
1.+(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 から生成された YACC クローン生成パーサーを使用しない唯一の 4 つの Ruby 実装はparse.y
、Cardinal、tinyrb、RubyGoLightly、および XRuby です。
Cardinal は Parrot 仮想マシンの Ruby 実装であり、Parrot には Parrot Grammar Engine が含まれているため、Cardinal は当然それを使用します。興味深いファイルはsrc/parser/grammar.pg
. PGE はハイブリッド再帰降下パーサー/演算子優先パーサーです。つまり、演算子の優先順位は文法ファイルに非常にうまく表示されます。
Tinyrb は、Ian Piumarta のレッグ ライブラリを利用した PEG パーサーを使用します。PEG パーサーでは一般的であるように、演算子の優先順位テーブルはなく、優先順位は文法の階層構造に暗示されています。詳細vm/grammar.leg
については、を参照してください。RubyGoLightly は tinyrb から派生したものですが、実装言語として C ではなく Go を使用していますが、同じ PEG 文法を使用しています。
XRuby はパーサーに ANTLR を使用します。ここで、興味深いファイルはsrc/com/xruby/compiler/parser/ruby.g
.
Rubinius は Melbourne パーサーを使用します。これは、基本的に 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 の構文しか処理しません。演算子の優先順位は扱いません。
言語ドキュメントの「演算子式」には、メソッドとしてオーバーライドできる演算子の表が示されています。独自の演算子を作成することはできません — 記号名への演算子のマッピングは、パーサーの内部にあります。
はい、固定されているため、新しい演算子を追加したり、既存の演算子の優先順位を変更したりすることはできません。