Ventajas de Antlr (versus say, lex / yacc / bison) [cerrado]

143

He usado lex y yacc (más generalmente bison) en el pasado para varios proyectos, generalmente traductores (como un subconjunto de EDIF transmitido a una aplicación EDA). Además, he tenido que admitir código basado en gramáticas lex / yacc que datan de décadas. Así que conozco las herramientas, aunque no soy un experto.

He visto comentarios positivos sobre Antlr en varios foros en el pasado, y tengo curiosidad por saber qué me estoy perdiendo. Entonces, si ha usado ambos, dígame qué es mejor o más avanzado en Antlr. Mis limitaciones actuales son que trabajo en una tienda de C ++, y cualquier producto que enviemos no incluirá Java, por lo que los analizadores resultantes tendrían que seguir esa regla.

Don Wakefield
fuente

Respuestas:

145

Actualización / advertencia: ¡Esta respuesta puede estar desactualizada!


Una diferencia importante es que ANTLR genera un analizador LL (*), mientras que YACC y Bison generan analizadores que son LALR. Esta es una distinción importante para una serie de aplicaciones, siendo los operadores más obvios:

expr ::= expr '+' expr
       | expr '-' expr
       | '(' expr ')'
       | NUM ;

ANTLR es completamente incapaz de manejar esta gramática tal como está. Para usar ANTLR (o cualquier otro generador de analizador LL), necesitaría convertir esta gramática en algo que no sea recursivo a la izquierda. Sin embargo, Bison no tiene problemas con las gramáticas de esta forma. Debería declarar '+' y '-' como operadores asociativos a la izquierda, pero eso no es estrictamente necesario para la recursividad izquierda. Un mejor ejemplo podría ser el despacho:

expr ::= expr '.' ID '(' actuals ')' ;

actuals ::= actuals ',' expr | expr ;

Observe que tanto las reglas exprcomo las actualsreglas son recursivas a la izquierda. Esto produce un AST mucho más eficiente cuando llega el momento de generar código porque evita la necesidad de múltiples registros y derrames innecesarios (un árbol de inclinación izquierda puede colapsarse mientras que un árbol de inclinación derecha no).

En términos de gusto personal, creo que las gramáticas LALR son mucho más fáciles de construir y depurar. La desventaja es que tienes que lidiar con errores algo crípticos como shift-reduce y (el temido) reduce-reduce. Estos son errores que Bison detecta al generar el analizador, por lo que no afecta la experiencia del usuario final, pero puede hacer que el proceso de desarrollo sea un poco más interesante. ANTLR generalmente se considera más fácil de usar que YACC / Bison precisamente por esta razón.

Daniel Spiewak
fuente
2
Entonces, ¿la gran ventaja de Antlr, posiblemente única, en su percepción es que genera menos errores como sr y rr durante la fase de construcción? Espero intentarlo, pero probablemente terminaré con lo que sé ...
Don Wakefield
1
Sí, eso es todo. :-) Tampoco estoy de acuerdo con la opinión popular de que ANTLR es más fácil que Bison, por lo que creo que estaría de acuerdo con su decisión.
Daniel Spiewak
2
¿La regla 'actuals' necesita una segunda regla para indicar que un simple 'expr' es un actual? De lo contrario, buena explicación.
Jonathan Leffler
8
Otro comentario que encontré recientemente, aunque tiene una década de antigüedad, hace una observación razonable de la producción : compilers.iecc.com/comparch/article/98-11-040 : "ANTLR / PCCTS son LL, lo que dificulta la escritura gramatical, pero el el código generado es legible. Yacc es LALR (por supuesto que lo sabe) hace que la escritura gramatical sea más fácil, pero el código generado también podría ser jeroglíficos ".
Don Wakefield el
72
Acabo de completar el soporte inmediato de recursión izquierda para la próxima versión de ANTLR v3.4. Maneja las reglas de expresión LR y cosas similares como las reglas del declarador C. :)
Terence Parr
117

La diferencia más significativa entre YACC / Bison y ANTLR es el tipo de gramáticas que estas herramientas pueden procesar. YACC / Bison manejan las gramáticas LALR, ANTLR maneja las gramáticas LL.

A menudo, las personas que han trabajado con gramáticas LALR durante mucho tiempo, encontrarán que trabajar con gramáticas LL es más difícil y viceversa. Eso no significa que las gramáticas o herramientas sean inherentemente más difíciles de trabajar. La herramienta que le resulte más fácil de usar se reducirá principalmente a la familiaridad con el tipo de gramática.

En cuanto a las ventajas, hay aspectos donde las gramáticas LALR tienen ventajas sobre las gramáticas LL y hay otros aspectos donde las gramáticas LL tienen ventajas sobre las gramáticas LALR.

YACC / Bison generan analizadores de tabla, lo que significa que la "lógica de procesamiento" está contenida en los datos del programa analizador, no tanto en el código del analizador. La recompensa es que incluso un analizador de un lenguaje muy complejo tiene una huella de código relativamente pequeña. Esto fue más importante en las décadas de 1960 y 1970, cuando el hardware era muy limitado. Los generadores de analizadores de tabla se remontan a esta época y la huella de código pequeña era un requisito principal en ese momento.

ANTLR genera analizadores de descenso recursivos, lo que significa que la "lógica de procesamiento" está contenida en el código del analizador, ya que cada regla de producción de la gramática está representada por una función en el código del analizador. La recompensa es que es más fácil entender lo que hace el analizador leyendo su código. Además, los analizadores de descenso recursivo suelen ser más rápidos que los de mesa. Sin embargo, para lenguajes muy complejos, la huella del código será mayor. Este fue un problema en los años sesenta y setenta. En aquel entonces, solo idiomas relativamente pequeños como Pascal, por ejemplo, se implementaron de esta manera debido a limitaciones de hardware.

Los analizadores generados por ANTLR están típicamente cerca de 10.000 líneas de código y más. Los analizadores de descenso recursivos escritos a mano suelen estar en el mismo estadio. El compilador Oberon de Wirth es quizás el más compacto con aproximadamente 4000 líneas de código, incluida la generación de código, pero Oberon es un lenguaje muy compacto con solo unas 40 reglas de producción.

Como alguien ya ha señalado, una gran ventaja para ANTLR es la herramienta gráfica IDE, llamada ANTLRworks. Es un laboratorio completo de diseño de gramática y lenguaje. Visualiza sus reglas gramaticales a medida que las escribe y, si encuentra algún conflicto, le mostrará gráficamente cuál es el conflicto y qué lo causa. Incluso puede refactorizar y resolver automáticamente conflictos como la recursión izquierda. Una vez que tenga una gramática libre de conflictos, puede dejar que ANTLRworks analice un archivo de entrada de su idioma y cree un árbol de análisis y AST para usted y muestre el árbol gráficamente en el IDE. Esta es una gran ventaja porque puede ahorrarle muchas horas de trabajo: ¡Encontrará errores conceptuales en el diseño de su lenguaje antes de comenzar a codificar! No he encontrado ninguna herramienta de este tipo para las gramáticas LALR, parece que no existe tal herramienta.

Incluso para las personas que no desean generar sus analizadores, sino que los codifican manualmente, ANTLRworks es una gran herramienta para el diseño / creación de prototipos del lenguaje. Posiblemente la mejor herramienta disponible. Desafortunadamente, eso no te ayuda si quieres construir analizadores LALR. Puede que valga la pena cambiar de LALR a LL simplemente para aprovechar ANTLRworks, pero para algunas personas, cambiar los tipos de gramática puede ser una experiencia muy dolorosa. En otras palabras: YMMV.

trijezdci
fuente
44
me gusta porque explica la historia detrás de los diferentes mecanismos que hacen que las personas entiendan de
inmediato
35

Un par de ventajas para ANTLR:

  • puede generar analizadores en varios idiomas: Java no es necesario para ejecutar el analizador generado.
  • La impresionante GUI facilita la depuración gramatical (por ejemplo, puede ver los AST generados directamente en la GUI, no se requieren herramientas adicionales)
  • El código generado es en realidad legible para los humanos (es uno de los objetivos de ANTLR) y el hecho de que genera analizadores LL seguramente ayuda en este sentido.
  • la definición de terminales también está libre de contexto (a diferencia de la expresión regular en (f) lex), lo que permite, por ejemplo, la definición de terminales que contienen paréntesis correctamente cerrados

Mi .02 $

Cristian Diaconescu
fuente
9

Otra ventaja de ANTRL es que puede usar ANTLRWORKS , aunque no puedo decir que sea una ventaja estricta, ya que puede haber herramientas similares para otros generadores también.

John con gofres
fuente
9
  • Bison y Flex resultan en una huella de memoria más pequeña, pero no tiene IDE gráfico.
  • antlr usa más memoria, pero tienes antlrworks, un IDE gráfico.

El uso de la memoria Bison / Flex es típicamente un mbyte más o menos. Compare eso con antlr, suponiendo que use 512 bytes de memoria para cada token en el archivo que desea analizar. 4 millones de tokens y ya no tiene memoria virtual en un sistema de 32 bits.

Si el archivo que desea analizar es grande, antlr puede quedarse sin memoria, por lo que si solo desea analizar un archivo de configuración, sería una solución viable. De lo contrario, si desea analizar un archivo con muchos datos, intente con Bison.

solo yo
fuente
77
Soy curioso. ¿Puede señalar la documentación que describe el consumo de 512 bytes de memoria por token? No recuerdo haber visto esa discusión. Mi elección de palabras clave de Google tampoco me da satisfacción ...
Don Wakefield
2
¿Está hablando de la huella de memoria del generador de analizador mientras genera un analizador, o está hablando de la huella de memoria del analizador generado mientras analiza la entrada para el idioma de origen? Millones de fichas en una gramática sería absolutamente una locura. Debería estar encerrado en una institución mental si intentara seriamente vender esa idea. En cuanto a los archivos de entrada para el analizador en sí, puede haber casos en los que estos tengan una cantidad extremadamente grande de tokens, pero la mayoría de los idiomas son modulares, no analiza la entrada completa en un solo archivo, los módulos individuales son más pequeños.
trijezdci