2010-02-13 6 views
7

La plupart des choses qui ressemblent à des opérateurs sont des méthodes dans Ruby; 1 + 2 est le sucre syntaxique pour 1.+(2).Opérateurs et méthodes dans Ruby

Même si + et * sont des méthodes qu'un programme peut redéfinir, Ruby a la magie spéciale pour évaluer 1 + 2 * 3 comme 1.+(2.*(3)) au lieu de 1.+(2).*(3).

Je me demande où cette magie spéciale vit dans Ruby - si elle est câblée dans l'interprète.

Ari.

Répondre

10

Dans toutes les implémentations Ruby, la priorité de l'opérateur est gérée par l'analyseur. Comme pratiquement toutes les implémentations Ruby existantes utilisent le même analyseur, ou un analyseur généré à partir de la même grammaire YACC, parse.y in YARV is the file you want to look at. (En JRuby, par exemple, ce fichier est essentiellement le même:. src/org/jruby/parser/Ruby19Parser.y Idem pour IronRuby. Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.y)

Les seuls quatre Ruby Implémentations qui ne pas soit utiliser l'analyseur YARV directement ou utiliser un analyseur généré clone YACC de parse.y de YARV, sont Cardinal, tinyrb, RubyGoLightly et XRuby. Cardinal est une implémentation de Ruby pour la machine virtuelle Parrot, et comme Parrot inclut le Parrot Grammar Engine, Cardinal l'utilise naturellement. Le fichier intéressant est src/parser/grammar.pg. PGE est un analyseur de priorité hybride récursif-parseur/opérateur hybride, ce qui signifie que la précédence de l'opérateur apparaît assez bien dans le fichier de grammaire. Tinyrb utilise un analyseur PEG utilisant la bibliothèque de pied de Ian Piumarta. Comme il est typique pour les analyseurs PEG, il n'y a pas de table de priorité d'opérateur, mais la préséance est implicite dans la structure hiérarchique de la grammaire. Voir vm/grammar.leg pour plus de détails. RubyGoLightly est dérivé de tinyrb, sauf qu'il utilise Go au lieu de C comme langage d'implémentation, mais il utilise la même grammaire PEG.

XRuby utilise ANTLR pour son analyseur. Ici, le fichier intéressant est src/com/xruby/compiler/parser/ruby.g. Rubinius utilise l'analyseur de Melbourne, qui est essentiellement l'analyseur de YARV emballé comme extension C. MagLev utilise ruby_parser (voir ci-dessous). Outre les implémentations Ruby, il existe également d'autres analyseurs Ruby disponibles. Ruby_parser de Ryan Davis est dérivé de la grammaire YARV YACC. Il utilise racc comme générateur d'analyseur. Voir lib/ruby_parser.y. RedParse de Caleb Clausen utilise l'interpréteur-compilateur manuscrit de Caleb. Le fichier intéressant est lib/redparse/babyparser.rb.

C'est tous les analyseurs que je connais, qui gèrent la priorité des opérateurs.Il y a un autre analyseur dans RDoc, et il y en avait un dans YARD (il utilise maintenant RedParse), mais ceux-ci ne gèrent que la syntaxe de Ruby pour trouver les modules, classes et méthodes, les commentaires et extraire les listes de paramètres. Ils ne traitent pas de la priorité des opérateurs.

+0

Merci. Votre réponse est très détaillée et a d'excellents pointeurs sur les fichiers, y compris les numéros de ligne. Cela dépasse largement mes attentes. Je recherche certaines de vos autres réponses et en apprends beaucoup sur les implémentations de Ruby. Merci de partager vos connaissances. – iter

+0

De rien! –

0

Oui, il est câblé, donc vous ne pouvez pas ajouter de nouveaux opérateurs ou modifier la priorité des opérateurs existants.

2

"Operator Expressions" dans la documentation du langage donne une table avec les opérateurs qui peuvent être remplacés en tant que méthodes. Vous ne pouvez pas créer vos propres opérateurs - le mappage des opérateurs sur leurs noms de symboles reste à l'intérieur de l'analyseur.

+0

Merci pour le lien - je suis un familier avec lui et aurait dû l'inclure dans la question. Je suis à la recherche d'une réponse plus précise que "vit vraisemblablement à l'intérieur de l'analyseur". Peut-être que je peux l'exprimer ainsi: si je voulais fourrer ma propre version de Ruby où '*' avait une priorité inférieure à '+', quel (s) fichier (s) changerais-je? Ari. – iter