¿Los lenguajes modernos todavía usan generadores de analizadores sintácticos?

38

Estaba investigando sobre el conjunto de compiladores gcc en wikipedia aquí , cuando surgió esto:

GCC comenzó usando analizadores LALR generados con Bison, pero gradualmente cambió a analizadores de descenso recursivo escritos a mano; para C ++ en 2004, y para C y Objective-C en 2006. Actualmente, todos los front-end utilizan analizadores de descenso recursivo escritos a mano

Entonces, en esa última oración, (y por mucho que confíe en wikipedia) definitivamente puedo decir que "C (gcc), C ++ (g ++), Objective-C, Objective-C ++, Fortran (gfortran), Java (gcj), Ada (GNAT), Go (gccgo), Pascal (gpc), ... Mercury, Modula-2, Modula-3, PL / I, D (gdc) y VHDL (ghdl) "son todos los extremos que no Ya no use un generador de analizador. Es decir, todos usan analizadores escritos a mano.

Mi pregunta es, ¿es esta práctica omnipresente? Específicamente, estoy buscando respuestas exactas a "¿la implementación estándar / oficial de x tiene un analizador escrito a mano" para x en [Python, Swift, Ruby, Java, Scala, ML, Haskell]? (En realidad, la información en cualquier otro idioma también es bienvenida aquí.) Estoy seguro de que puedo encontrar esto por mi cuenta después de mucho excavar. Pero también estoy seguro de que esto es fácil de responder por la comunidad. ¡Gracias!

eatonphil
fuente
3
Punto de datos: CPython tiene un generador de analizador LALR (pgen) de preparación casera. No sé sobre el resto.
8
Punto de datos: Ghc (haskell) utiliza un generador de analizador LALR (contento), al igual que OCaml.
Twan van Laarhoven
1
Debería ser "Hacer compiladores modernos de alto rendimiento ..." o similar, porque el lenguaje es la especificación, no la implementación, mientras que es el compilador el que usa o no usa un analizador generado por máquina.
dmckee
@dmckee, sí, tienes razón. Sin embargo, la denominación comienza a ser larga y menos al grano. ¡Siéntete libre de editarlo si eres más creativo que yo!
eatonphil
Con respecto a ML: MLton usa un generador de analizador específico para ML, estoy 90% seguro de que SML / NJ también lo hace, aunque estoy menos familiarizado con él. Es posible que desee o no considerar eso "escrito a mano".
Patrick Collins

Respuestas:

34

AFAIK, GCC utilizan analizadores escritos a mano en particular para mejorar el diagnóstico de errores sintácticos (es decir, dar mensajes humanos significativos sobre errores de sintaxis).

La teoría de análisis (y los generadores de análisis que descienden de ella) se trata principalmente de reconocer y analizar una frase de entrada correcta . Pero esperamos de los compiladores que den un mensaje de error significativo (y que puedan analizar de manera significativa el resto de la entrada después del error sintáctico), por alguna entrada incorrecta.

Además, los lenguajes heredados antiguos, como C11 o C ++ 11, (que son conceptualmente antiguos, incluso si su última revisión tiene solo tres años) no están en absoluto libres de contexto. Tratar con esa sensibilidad al contexto en las gramáticas para los generadores de analizadores sintéticos (es decir, bisontes o incluso menhires ) es aburridamente difícil.

Basile Starynkevitch
fuente
2
Concurrir. Recuperarse bien de los errores de análisis (cuando no desea dejar de analizar el primer error, al estilo del antiguo Borland Pascal) y crear mensajes de error de buena calidad (incluidas sugerencias y sugerencias de resolución, como los humanos quieren) son inherentemente contextuales. -tareas sensibles, heurísticas. Se pueden hacer sobre la salida del generador de analizador de acciones, de alguna manera, pero es un trabajo pesado.
Jonathan Eunice
2
Dealing with that context sensitiveness in grammars for parser generators is boringly difficult. También es más o menos imposible ya que estas herramientas generan analizadores sin contexto. El lugar correcto para verificar si todas las restricciones sensibles al contexto están presentes es después de haber generado el árbol de análisis si está utilizando herramientas como esta.
dtech
7

Los generadores del analizador y los motores del analizador son bastante generales. La ventaja de la generalidad es que construir un analizador preciso rápidamente y hacerlo funcional es fácil, en el esquema general de las cosas.

El motor de análisis en sí mismo sufre en el frente de rendimiento debido a su generalidad. Cualquier código escrito a mano siempre será significativamente más rápido que los motores de análisis de tablas.

La segunda área donde los generadores / motores analizadores tienen dificultades es que todos los lenguajes de programación reales son sensibles al contexto, a menudo de manera bastante sutil. Los lenguajes LR no tienen contexto, lo que significa que hay muchas sutilezas sobre el posicionamiento y el entorno que son imposibles de transmitir adecuadamente en la sintaxis. Los grammers atribuidos intentan abordar las reglas básicas del lenguaje como "declarar antes de usar", etc. El cableado de esta sensibilidad al contexto en código escrito a mano es sencillo.

BobDalgleish
fuente
15
¿Cita para el reclamo de rendimiento por favor? Ser impulsado por tablas puede ser una optimización de rendimiento significativa y los generadores tienen acceso a algoritmos que son muy eficientes pero que prácticamente nunca se implementan a mano (precisamente porque son un desastre impenetrable de tablas y números mágicos).
2
Y sobre la segunda área: muchos de los principales lenguajes de programación reales no son sensibles al contexto en ningún sentido aplicable (tendrías que referirte al conjunto de todos los programas válidos después de la verificación de tipo y tal, que nunca es lo que se escribe a mano o el analizador generado intenta analizar). Es cierto que los analizadores escritos a mano son más flexibles, y esto es útil para algunos idiomas, pero principalmente en el ámbito de la recuperación de errores e informes, incrementalidad, etc., los generadores de analizadores rara vez se evitan debido al poder de reconocimiento (ya sea querer escribir esa gramática es una historia diferente). -1
Si usa la información de la tabla de símbolos durante el análisis, también podría llamarla sensible al contexto. Las gramáticas atribuidas definitivamente no están libres de contexto, aunque no creo que sean completamente sensibles al contexto. Sus otros puntos sobre recuperación de errores e informes están bien tomados.
BobDalgleish
1
C y C ++ necesitan información de la tabla de símbolos durante el análisis (o aceptan un árbol de análisis mucho menos específico donde no se hace distinción entre, por ejemplo, declaraciones de expresión y declaraciones de variables). Pero no estaba pensando en eso. Los lenguajes como Java, Lisps, JavaScript, Ruby, Python, Go, Rust, Scala, Swift, Haskell (y probablemente varios más, ¿tal vez C # y ML también?) No necesitan dicha información para construir el tipo de AST quiere de todos modos. Muchos de ellos en realidad tienen gramáticas LL (1), o incluso gramáticas LALR.
1
Las citas para todos los idiomas reales son sensibles al contexto, por favor.
psr