2008-12-10 13 views
9

¿Cómo definiría sus reglas de analizador y lexer para analizar un lenguaje que utiliza sangría para definir el alcance.¿Cómo analizarías la sangría (estilo de pitón)?

Ya he buscado en Google y encontré un enfoque inteligente para analizarlo generando tokens INDENT y DEDENT en el lexer.

Voy a profundizar en este problema y publicar una respuesta si llego a algo interesante, pero me gustaría ver otros enfoques para el problema.

EDITAR: Como Charlie señaló, there is already another thread very similar if not the same. ¿Debería eliminarse mi publicación?

Respuesta

1

También puede rastrear en algún lugar en lexer cuántos elementos ident están precediendo a la primera línea y pasarlos al analizador. La parte más interesante sería tratar de pasarlo al analizador correctamente :) Si su analizador usa el análisis anticipado (aquí quiero decir que el analizador puede consultar el número variable de tokens antes de que realmente vaya a coincidir con uno), parece que tratar de pasarlo a través de una variable global parece ser una muy mala idea (porque Lexer puede deslizarse en la siguiente línea y cambiar el valor del contador de sangrado mientras el analizador aún está tratando de analizar la línea anterior). También los globales son malvados en muchos otros casos;) Marcar el token de 'línea' de primera línea de alguna manera con un contador de sangría es más razonable. No puedo darte el ejemplo exacto (ni siquiera sé qué generador de analizadores sintácticos y lexers usarás si es que ...) pero algo así como almacenar datos en tokens de primera línea (podría ser incómodo si puedes " t obtener fácilmente dicho token del analizador) o guardar datos personalizados (mapa que vincula tokens a sangría, matriz donde cada línea en código fuente como índice y valor de sangría como valor de elemento) parece ser suficiente. Una desventaja de este enfoque es la complejidad adicional del analizador sintáctico que deberá distinguir entre los valores ident y cambiar su comportamiento en función de este. Algo como LOOKAHEAD ({yourConditionInJava}) para JavaCC puede funcionar aquí pero es NOT una muy buena idea. Una gran cantidad de tokens adicionales en su enfoque parece ser menos mal uso :)

Como otra alternativa que sugeriría es mezclar estos dos enfoques. Puede generar tokens adicionales solo cuando el contador de sangría cambie su valor en la siguiente línea. Es como el token BEGIN y END artificial. De esta forma, puedes disminuir el número de tokens 'artificiales' en tu flujo alimentado al analizador desde el lexer. Solo la gramática del analizador debe ajustarse para comprender tokens adicionales ...

No probé esto (no tengo experiencia con el análisis de dichos lenguajes), solo compartí mis ideas sobre posibles soluciones. Verificar los analizadores ya compilados para este tipo de idiomas podría ser de gran valor para usted. El código abierto es tu amigo;)

10

Esto es un tanto hipotético, ya que dependería de la tecnología que tengas para tu lector y analizador, pero la manera más fácil sería tener los tokens BEGINBLOCK y ENDBLOCK análogos a los paréntesis en C. Usando el "offsides rule", su lector necesita hacer un seguimiento de una pila de niveles de indendtation. Cuando el nivel de sangría aumenta, se emite un BEGINBLOCK para el analizador sintáctico; cuando el nivel de sangría disminuye, emite ENDBLOCK y elimina los niveles de la pila.

Here's another discussion de esto en SO, btw.

Cuestiones relacionadas