Compiladores, Python
     

Introducción a ANTLR para Python

ANTLR es una herramienta de escritura del compilador, similar Lex/Yacc o Flex/Bison pero mucho más capaz, moderna y generalmente menos frustrante. Actualmente estoy leyendo a través de The Definitive ANTLR 4 Reference por el creador de ANTLR, Terence Parr. Es un reasource maravilloso en el funcionamiento y el uso de ANTLR, pero está escrito en Java – uno de mis idiomas menos favoritos. Afortunadamente ANTLR se dirige a varios idiomas, así que pensé en seguir en Python, también uno de mis idiomas menos favoritos.

ANTLR está escrito en Java, por lo que independientemente del idioma en el que escriba (Python en este caso) necesitará tener Java instalado, descargar el archivo ANTLR Jar y una configuración de Java Classpath en su entorno de shell. Suponiendo que estés usando Fish, eso se parece a esto:

Con eso fuera del camino, ya hemos terminado con Java. Podemos pasar a pasos más específicos de Python, y el primero es instalar el tiempo de ejecución de Python ANTLR. Eso es tan simple como ejecutar pip install:

El último bit de configuración es configurar un alias para invocar la propia herramienta ANTLR. Si bien esto es puramente opcional, me parece que ahorra mucho mecanografía. Esto es similar al script de la página 5 del libro ANTLR, pero adaptado para Python.

Nota: Asegúrese de chmod +x el script anterior y colóquelo en algún lugar dentro de su ruta.

Ahora podemos volver a disfrutar aprendiendo sobre ANTLR. En su mayor parte, seguir junto con el libro es un proceso de traducción directa, con los nombres de clase Java a los que se hace referencia en el libro son muy similares (si no idénticos) a los expuestos por el marco ANTLR de Python.

Por ejemplo, aquí hay un archivo “principal” de ejemplo para invocar su gramática:

Simplemente cambia “YourLexer” y “YourParser” por los nombres apropiados de su lexer y analizador.

Incluso la creación de visitantes y oyentes es más o menos una traducción 1:1 de sus ejemplos de Java del libro. Por ejemplo, un blueprint para un agente de escucha podría tener el siguiente aspecto:

En realidad es muy agradable que las conveciones utilizadas por el tiempo de ejecución de Java son tan muy similares a las utilizadas por el de Python. Sospecho que esto es intencional, ya que para reducir la cantidad de trabajo necesario para agregar nuevos objetivos de lenguaje, y reducir la complejidad de su documentación.

Sin embargo, todo esto tiene un inconveniente.

A pesar del lenguaje que implica el contario en el propio libro ANTLR, las gramáticas ANTLR no son agnósticas del lenguaje. Es totalmente posible restringir una gramática ANTLR que no se puede compilar tal cual a ningún número de idiomas de destino. De hecho, nos encontramos con esta situación bastante temprano en el libro en la página 43 donde estamos expuestos al patrón de escucha.

La gramática Java.g4 no funciona cuando se dirige a Python, ANTLR genera los siguientes errores:

¡Eso son muchos errores!

Vamos a sacar el primer error real y mirar un poco más de cerca.

Se queja de que la regla “tipo” nos está causando problemas. Para entender mejor por qué, echemos un vistazo a la parte aplicable de la gramática:

Y también el analizador Java generado por este poco de gramática:

Y, si no es 100% claro, echemos un vistazo al código Java que necesitaríamos para port a Python para utilizar esta gramática:

En esencia, la gramática define una regla llamada “tipo”, pero “tipo” es una palabra reservada en Python. ANTLR sí mismo entonces produce un analizador que literalmente define una función llamada “tipo”, que aparentemente está bien en Java, pero falla maravillosamente en Python.

Este problema podría haberse evitado fácilmente mediante el uso de algún prefijo común para las reglas, o tener reglas que se busquen en un diccionario. En su lugar, al tomar nombres de reglas literales y esperar que cada uno de ellos se pueda definir como una función del mismo nombre exacto en el idioma de destino, ANTLR no es, por definición, independiente del lenguaje. Para cualquier gramática, es probable que haya varios backends reales o hipotéticos para los que tal gramática no se puede compilar.

Por ejemplo, aquí hay una gramática que funciona perfectamente bien en Python, pero no se puede compilar para Java:

Lamentablemente, este problema de github implica que este es también un problema conocido por el autor, y uno que no consideran que vale la pena solucionar.

Si bien muchas, si no la mayoría, las gramáticas probablemente no son un problema, es bastante triste que:

  1. Tal problema ocurre bastante temprano en el libro
  2. El libro implica mucho, y otros recursos en Internet francamente decir, que ANTLR es independiente del lenguaje – no es
  3. El autor no parece inclinado a corregir más ampliamente ni este error, o este concepto erróneo sobre su herramienta.

Aparte de eso, ANTLR es en realidad una herramienta maravillosa, especialmente si te metes en ella con conocimiento y conciencia de sus verrugas. Estoy emocionado de ver qué cosas maravillosas puedo crear con esta increíble herramienta.

About Jason

Jason es un experimentado emprendedor y desarrollador de software experto en liderazgo, desarrollo móvil, sincronización de datos y arquitectura SaaS. Obtuvo su Licenciatura en Ciencias de la Computación de la Universidad Estatal de Arkansas.
View all posts by Jason →

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *