2010-02-13 16 views
7

La mayoría de las cosas que parecen ser operadores son métodos en Ruby; 1 + 2 es azúcar sintáctico para 1.+(2).Operadores y métodos en Ruby

Aunque + y * son métodos que un programa puede redefinir, Ruby tiene magia especial para evaluar 1 + 2 * 3 como 1.+(2.*(3)) en lugar de 1.+(2).*(3).

Me pregunto dónde vive esta magia especial en Ruby, si está conectada al intérprete.

Ari.

Respuesta

10

En todas las implementaciones de Ruby, la precedencia del operador es manejada por el analizador. Dado que prácticamente todas las implementaciones de Ruby existentes usan el mismo analizador, o un analizador generado a partir de la misma gramática YACC, parse.y in YARV is the file you want to look at. (En JRuby, por ejemplo, ese archivo es esencialmente la misma:. src/org/jruby/parser/Ruby19Parser.y mismo para IronRuby:. Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.y)

Los únicos cuatro implementaciones de Ruby que hacen no utilizar el analizador YARV directamente o utilizar un analizador sintáctico YACC clon generado de YARV parse.y, son Cardinal, tinyrb, RubyGoLightly y XRuby.

Cardinal es una implementación de Ruby para la máquina virtual Parrot, y como Parrot incluye el Parrot Grammar Engine, Cardinal lo usa naturalmente. El archivo interesante es src/parser/grammar.pg. PGE es un analizador de precedencia de operador/analizador de descendencia recursivo híbrido, lo que significa que la precedencia del operador aparece muy bien en el archivo de gramática.

Tinyrb usa un analizador PEG que utiliza la biblioteca de piernas de Ian Piumarta. Como es típico para los analizadores PEG, no existe una tabla de precedencia del operador, sino que la precedencia está implícita en la estructura jerárquica de la gramática. Vea vm/grammar.leg para más detalles. RubyGoLightly se deriva de tinyrb, excepto que usa Go en lugar de C como el lenguaje de implementación, pero usa la misma gramática PEG.

XRuby usa ANTLR para su analizador. Aquí, el archivo interesante es src/com/xruby/compiler/parser/ruby.g.

Rubinius usa el analizador de Melbourne, que es esencialmente el analizador de YARV empaquetado como una extensión C. MagLev usa ruby_parser (ver a continuación).

Además de las implementaciones de Ruby, también hay otros analizadores de Ruby disponibles.

Ryan Davis's ruby_parser se deriva de la gramática YARV YACC. Utiliza racc como generador del analizador sintáctico. Ver lib/ruby_parser.y.

Caleb Clausen RedParse utiliza el compilador-intérprete escrito a mano de Caleb. El archivo interesante es lib/redparse/babyparser.rb.

Eso es todos los analizadores que conozco, que realmente manejan la precedencia del operador.Hay otro analizador integrado en RDoc, y solía haber uno en YARD (ahora usa RedParse), pero esos solo manejan lo suficiente de la sintaxis de Ruby para encontrar módulos, clases y métodos, comentarios y listas de parámetros de métodos de extracción. No tratan con la precedencia del operador.

+0

Gracias. Su respuesta es muy detallada y tiene excelentes indicaciones para los archivos, incluidos los números de línea. Excede grandemente mis expectativas. Busco algunas de sus otras respuestas y aprendo mucho sobre las implementaciones de Ruby. Gracias por compartir tu conocimiento. – iter

+0

¡De nada! –

0

Sí, está cableado, por lo que no puede agregar nuevos operadores ni cambiar la precedencia de los operadores existentes.

2

"Operator Expressions" en la documentación del idioma se proporciona una tabla con los operadores que se pueden anular como métodos. No puede formar sus propios operadores: el mapeo de operadores a sus nombres de símbolos vive dentro del analizador.

+0

Gracias por el enlace, estoy familiarizado con él y debería haberlo incluido en la pregunta. Estoy buscando una respuesta más específica que "presumiblemente vive dentro del analizador sintáctico". Tal vez puedo expresarlo así: si quería bifurcar mi propia versión de Ruby, donde '*' tenía una prioridad menor que '+', qué archivo (s) cambiaría. Ari. – iter