Como proyecto paralelo, estoy escribiendo un lenguaje usando Python. Comencé usando un clon de flex / bison llamado Ply, pero estoy enfrentando los límites en el poder de lo que puedo expresar con ese estilo de gramática, y no estoy interesado en hackear mi lenguaje debido a un desajuste de impedancia con la herramienta. Por lo tanto, no soy reacio a escribir el mío.
Entonces, ¿cuál es el tipo de analizador más poderoso? Serían bienvenidas las citas a artículos (así como a más artículos introductorios).
(Sé que 'poderoso' no está definido con precisión, pero seamos un poco flojos y veamos a dónde van las respuestas)
fl.formal-languages
pl.programming-languages
grammars
Paul Biggar
fuente
fuente
Respuestas:
Una gramática generalmente se define como una gramática libre de contexto : se proporciona una definición precisa en la página de Wikipedia, pero funciona igual que en PLY, que se basa en Bison , que a su vez se basa en yacc .
Aquí dice que PLY usa un analizador LALR . Este es esencialmente un analizador LR donde las tablas de búsqueda se condensan, posiblemente introduciendo conflictos de análisis, reduciendo algo de la expresividad de una gramática LR (es decir, una gramática libre de contexto que un analizador LR puede analizar). Si usted quiere saber acerca de las limitaciones de esta rama particular de analizadores y los de otros programas de análisis, se da una visión general de todo tipo de técnicas de análisis sintáctico (LL, LR y otros) aquí .
Para responder a su pregunta: existen algoritmos de análisis capaces de analizar cualquier lenguaje sin contexto, incluso si el lenguaje es ambiguo (es decir, hay más de una forma de interpretar la entrada):
El primer algoritmo fue el algoritmo CYK , que desafortunadamente tiene un tiempo de ejecución de , donde es la longitud de la cadena de entrada yes el tamaño de la gramática y, por lo tanto, no es práctico para analizar idiomas.n | G |O ( n3El | G | ) norte El | G |
El segundo algoritmo es el algoritmo de Earley . Este algoritmo también es capaz de analizar cualquier gramática libre de contexto. Aunque el algoritmo necesita tiempo para analizar un lenguaje ambiguo, solo necesita tiempo para analizar un lenguaje no ambiguo. Además, aparentemente funciona en tiempo lineal para la mayoría de las gramáticas LR y funciona particularmente bien en las gramáticas recursivas a la izquierda.O ( n 2 )O ( n3) O ( n2)
Aquí puede encontrar un documento que discute una implementación práctica del (algoritmo de Earley). Concluyen: "Dada la generalidad del análisis de Earley en comparación con el análisis LALR (1) ((que es más o menos lo que hace PLY)), y considerando que incluso los PEP ((su implementación del algoritmo de Earley)) el peor momento no sería notable por un usuario, este es un excelente resultado ".
El último tipo de analizador es el analizador GLR . Esta es una versión generalizada del análisis LR, capaz de analizar cualquier lenguaje sin contexto.
Una implementación madura de GLR es ASF + SDF . Bison también puede generar un analizador GLR, aunque sus implementaciones son ligeramente diferentes del algoritmo GLR 'estándar'. El algoritmo de Elkhound es un algoritmo híbrido GLR / LALR. Utiliza LALR cuando es posible y GLR cuando es necesario, para ser rápido y capaz de analizar cualquier gramática.
Más allá de las gramáticas libres de contexto, hay gramáticas sensibles al contexto , pero en general son difíciles de analizar y no agregan tanta expresividad: puede hacer más con ellas, pero para la mayoría de las aplicaciones los usos adicionales no son relevantes, a menos que esté analizando Un lenguaje natural.
Como paso final hay gramáticas sin restricciones . En este punto, la gramática es completa de Turing, por lo que no hay límite que se pueda dar sobre cuánto tiempo llevará analizar un idioma en particular, lo que no es deseable para la mayoría de las aplicaciones de análisis. El poder extra casi nunca es necesario. Si desea utilizar toda esa potencia, existe la máquina de idiomas disponible.
Por último, implementar su propio generador de analizadores no es un asunto trivial, en particular para que sea rápido. Personalmente, acabo de terminar de hacer mi propia versión de flex (el generador de lexer), y si bien esto parecía un ejercicio de problemas algorítmicos relativamente simples, se volvió bastante complejo hacerlo bien, en particular cuando intenté admitir Unicode. Considere usar una implementación ya existente en lugar de escribir la suya.
fuente
Un artículo en ICFP 2010 este año, Total Parser Combinators , describe una biblioteca de combinación de analizador de terminación comprobable y también establece que en esta biblioteca "los combinadores de analizador son lo más expresivos posible" dado que se garantiza que el analizador termina. Lamentablemente, no recuerdo la explicación que dio el autor de lo que significa "lo más expresivo posible", pero ciertamente parece relevante a su pregunta sobre el "poder".
fuente
Si desea ir más allá de las gramáticas libres de contexto para analizar los lenguajes de programación, pero aún así analizar en tiempo polinómico, puede recurrir a analizar las gramáticas de expresión o las gramáticas booleanas ; estas últimas también están disponibles en sabores LL y LR (ver aquí ). En la teoría del lenguaje formal, también se estudian los lenguajes de Church-Rosser poderosos pero reconocibles en tiempo lineal , pero no conozco ningún generador de analizadores implementado para estos.
En el procesamiento del lenguaje natural, los gustos son diferentes, por ejemplo, lidiar con la ambigüedad (también: ambigüedad inherente) y el orden de las palabras libres juega un papel muy destacado. Aquí las palabras clave lenguajes ligeramente sensibles al contexto y reiniciar autómatas pueden ayudarlo a comenzar a leer.
fuente
Herramientas del generador de analizadores:
ANTLR es muy bueno. Alternativamente, puede echar un vistazo a JavaCC
fuente