Cuando comencé a usar los combinadores de analizador sintáctico, mi primera reacción fue una sensación de liberación de lo que parecía una distinción artificial entre analizador y lexing. De repente, ¡todo se estaba analizando!
Sin embargo, recientemente encontré esta publicación en codereview.stackexchange que ilustra a alguien que restablece esta distinción. Al principio pensé que esto era muy tonto de ellos, pero luego el hecho de que existan funciones en Parsec para apoyar este comportamiento me lleva a cuestionarme.
¿Cuáles son las ventajas / desventajas de analizar sobre una secuencia ya lexed en combinadores analizadores?
parsing
lexer
parser-combinator
Eli Frey
fuente
fuente
Respuestas:
Bajo análisis, entendemos con mayor frecuencia el análisis de lenguajes libres de contexto. Un lenguaje libre de contexto es más poderoso que uno normal, por lo tanto, el analizador puede (muy a menudo) hacer el trabajo del analizador léxico de inmediato.
Pero, esto es a) bastante antinatural b) a menudo ineficiente.
Para a), si pienso en cómo se
if
ve una expresión, por ejemplo , creo que SI expr ENTONCES expr ELSE expr y no 'i' 'f', tal vez algunos espacios, entonces cualquier carácter con el que una expresión pueda comenzar, etc. idea.Para b) hay herramientas poderosas que hacen un excelente trabajo al reconocer entidades léxicas, como identificadores, literales, corchetes de todo tipo, etc. Ellos harán su trabajo prácticamente en ningún momento y le brindarán una interfaz agradable: una lista de tokens. Ya no te preocupes por omitir espacios en el analizador, tu analizador será mucho más abstracto cuando se trata de fichas y no de personajes.
Después de todo, si crees que un analizador debería estar ocupado con cosas de bajo nivel, ¿por qué entonces procesar los personajes? ¡Se podría escribir también en el nivel de bits! Usted ve, un analizador que funciona en el nivel de bits sería casi incomprensible. Es lo mismo con los personajes y tokens.
Solo mis 2 centavos.
fuente
if = string "if" >> expr >> string "then" >> expr >> string "else" >> expr
.Todo el mundo sugiere que separar el lexing y el parsing es una "buena práctica", tengo que estar en desacuerdo, en muchos casos realizar lexing y parsing en una sola pasada proporciona mucho más poder, y las implicaciones de rendimiento no son tan malas como se presentan en el otras respuestas (ver Packrat ).
Este enfoque brilla cuando uno tiene que mezclar varios idiomas diferentes en una sola secuencia de entrada. Esto no solo es necesario para los extraños lenguajes orientados a la metaprogramación como Katahdin y similares , sino también para aplicaciones mucho más convencionales, como la programación alfabetizada (mezcla de látex y, por ejemplo, C ++), el uso de HTML en los comentarios, el relleno de Javascript en HTML, y pronto.
fuente
Un analizador léxico reconoce un lenguaje regular y un analizador reconoce un lenguaje libre de contexto. Dado que cada lenguaje regular también está libre de contexto (puede definirse mediante una llamada gramática lineal derecha ), un analizador también puede reconocer un lenguaje regular y la distinción entre analizador léxico y analizador parece agregar una complejidad innecesaria: un contexto único libre de gramática (analizador) podría hacer el trabajo de un analizador y un analizador léxico.
Por otro lado, puede ser útil capturar algunos elementos de un lenguaje sin contexto a través de un lenguaje regular (y, por lo tanto, un analizador léxico) porque
Por lo tanto, separar el análisis del análisis léxico tiene la ventaja de que puede trabajar con una gramática más simple y libre de contexto y encapsular algunas tareas básicas (a menudo rutinarias) en el analizador léxico (divide et impera).
EDITAR
No estoy familiarizado con los combinadores de analizador sintáctico, por lo que no estoy seguro de cómo se aplican las consideraciones anteriores en ese contexto. Mi impresión es que, incluso con los combinadores de analizador sintáctico, uno solo tiene una gramática libre de contexto, distinguir entre dos niveles (análisis léxico / análisis) podría ayudar a hacer que esta gramática sea más modular. Como se dijo, la capa inferior de análisis léxico podría contener analizadores básicos reutilizables para identificadores, literales, etc.
fuente
\alpha'_1 (K_0, \vec{T})
, donde \ alpha'_1, K_0 y \ vec {T} son identificadoresSimplemente, el lexing y el análisis deberían separarse porque son diferentes complejidades. Lexing es un DFA (autómata finito determinista) y un analizador es un PDA (autómata push-down). Esto significa que el análisis consume inherentemente más recursos que el lexing, y existen técnicas de optimización específicas disponibles solo para DFA. Además, escribir una máquina de estados finitos es mucho menos complejo y es más fácil de automatizar.
Está siendo un desperdicio al usar un algoritmo de análisis para lex.
fuente
Una de las principales ventajas de parse / lex por separado es la representación intermedia: el flujo de tokens. Esto se puede procesar de varias maneras que de otra manera no serían posibles con un lex / parse combinado.
Dicho esto, descubrí que un buen método recursivo decente puede ser menos complicado y más fácil de trabajar que aprender un generador de analizador, y tener que descubrir cómo expresar la debilidad de la gramática dentro de las reglas del generador de analizador sintáctico.
fuente