2010-02-13 8 views
7

Die meisten Dinge, die wie Operatoren aussehen, sind Methoden in Ruby; 1 + 2 ist syntaktischer Zucker für 1.+(2).Operatoren und Methoden in Ruby

Obwohl + und * Methoden sind, die ein Programm neu definieren kann, hat Rubin besonderen Zauber 1 + 2 * 3 als 1.+(2.*(3)) statt 1.+(2).*(3) zu bewerten.

Ich frage mich, wo diese spezielle Magie in Ruby lebt - wenn es in den Interpreter fest verdrahtet ist.

Ari.

Antwort

10

In allen Ruby-Implementierungen wird Operator Precedence vom Parser gehandhabt. Da praktisch alle vorhandenen Ruby-Implementierungen denselben Parser oder einen Parser verwenden, der aus derselben YACC-Grammatik generiert wurde, parse.y in YARV is the file you want to look at. (In JRuby zum Beispiel ist diese Datei im Wesentlichen die gleichen. src/org/jruby/parser/Ruby19Parser.y Das Gleiche gilt für IronRuby. Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.y)

Die einzigen vier Ruby-Implementierungen, die tun nicht entweder den YARV Parser verwenden, um direkt oder verwenden Sie einen YACC Klon erzeugt Parser von YARV parse.y, sind Cardinal, Tinyrb, RubyGoLightly und XRuby.

Cardinal ist eine Ruby-Implementierung für die virtuelle Parrot-Maschine, und da Parrot die Parrot Grammar Engine enthält, verwendet Cardinal dies natürlich. Die interessante Datei ist src/parser/grammar.pg. PGE ist ein hybrider Recursive-Descent-Parser/Operator-Precedence-Parser, was bedeutet, dass die Operator-Präzedenz in der Grammatikdatei ziemlich gut angezeigt wird.

Tinyrb verwendet einen PEG-Parser, der Ian Piumartas Beinbibliothek verwendet. Wie es für PEG-Parser typisch ist, gibt es keine Operatorpräzedenztabelle, vielmehr ist die Präzedenz implizit in der hierarchischen Struktur der Grammatik enthalten. Details finden Sie unter vm/grammar.leg. RubyGoLightly wird von tinyrb abgeleitet, außer dass es Go anstelle von C als Implementierungssprache verwendet, aber es verwendet die gleiche PEG-Grammatik.

XRuby verwendet ANTLR für seinen Parser. Hier ist die interessante Datei src/com/xruby/compiler/parser/ruby.g.

Rubinius verwendet den Melbourne-Parser, bei dem es sich im Wesentlichen um den YARV-Parser handelt, der als C-Erweiterung verpackt ist. MagLev verwendet ruby_parser (siehe unten).

Neben den Ruby-Implementierungen sind auch andere Ruby-Parser verfügbar.

Ryan Davis 'ruby_parser ist von der YARV YACC-Grammatik abgeleitet. Es verwendet racc als Parsergenerator. Siehe lib/ruby_parser.y.

Caleb Clausens RedParse verwendet Calebs eigenen, handgeschriebenen Compiler-Interpreter. Die interessante Datei ist lib/redparse/babyparser.rb.

Das sind alle Parser, die ich kenne, die tatsächlich die Vorrangstellung des Operators behandeln.Es gibt einen anderen Parser, der in RDoc integriert ist, und in YARD gab es einen solchen (er verwendet jetzt RedParse), aber diese behandeln nur gerade genug von Rubys Syntax, um Module, Klassen und Methoden, Kommentare und Methodenlisten zu finden. Sie befassen sich nicht mit der Priorität des Operators.

+0

Danke. Ihre Antwort ist sehr detailliert und hat ausgezeichnete Hinweise auf Dateien einschließlich Zeilennummern. Es übertrifft meine Erwartungen. Ich lese einige Ihrer anderen Antworten und lerne viel über Ruby-Implementierungen. Vielen Dank für Ihr Wissen. – iter

+0

Gern geschehen! –

0

Ja, es ist fest verdrahtet, Sie können also keine neuen Operatoren hinzufügen oder die Rangfolge der vorhandenen Operatoren ändern.

2

"Operator Expressions" in der Sprachdokumentation gibt eine Tabelle mit den Operatoren, die als Methoden überschrieben werden können. Sie können keine eigenen Operatoren erstellen - das Zuordnen von Operatoren zu ihren Symbolnamen lebt innerhalb des Parsers.

+0

Danke für den Link - ich kenne ihn und sollte ihn in die Frage aufgenommen haben. Ich suche nach einer spezifischeren Antwort als "vermutlich lebt innerhalb des Parsers." Vielleicht kann ich es so ausdrücken: Wenn ich meine eigene Version von Ruby abzweigen wollte, wobei '*' eine niedrigere Priorität als '+' hatte, würde ich die Datei (en) ändern. Ari. – iter