Allá por los '80 en la facultad me enseñaron los diagramas estructurados de Nassi-Schneiderman. Estos diagramas están buenos para leer código estructurado, y a veces garabateo alguno si tengo que armar una lógica complicada. Pero el código ajeno nunca existe en forma de diagrama, así que estaría bueno tener una herramienta que lo genere. Esa herramienta, además de ser útil, podría ser interesante de programar.
Problema #1: Generar el diagrama
Lo más práctico me pareció generar la salida en HTML con tablas, para ver algo parecido al diagrama Nassi-Schneiderman con un browser. Fue una buena opción. Las principales estructuras a visualizar son los condicionales (IF, THEN, ELSE) y los ciclos (FOR, WHILE, LOOP), y la forma en que se anidan.
Problema #2: Interpretar el código original
Dicho de otra manera: parsear. En la primera encarnación de la herramienta, en C++, parseaba a lo guapo, por no decir a lo bestia. No es que no se pueda parsear bien con C++, pero terminé con una implementación con limitaciones absurdas. Me metí en un berenjenal. Antes de parsear me veía obligado a toquetear el código de entrada para adecuarlo a ciertos requisitos inexcusables... por ejemplo, si había una cadena de ELSIF's:
IF cond1 THEN
sentencia1;
ELSIF cond2 THEN
sentencia2;
END IF;
...para que fuera parseable, tenía que modificarlo manualmente a:
IF cond1 THEN
sentencia1;
ELSE
IF cond2 THEN
sentencia2;
END IF;
END IF;
Creo que también hice una versión en C# que andaba mejor, pero el problema de fondo no estaba resuelto.
Combinator parsing al rescate
La técnica funcional salvadora fue combinator parsing, en este caso en Scala. No voy a incluir acá un tutorial de Scala ni voy a explicar cómo está implementada la librería (si bien vale la pena empaparse en el tema). Voy a enfocarme en el uso de la librería usando mi proyecto como ejemplo. Van a notar que parece un lenguaje con soporte especial para parsing, pero es solo una ilusión: el lenguaje es lo suficientemente flexible, porque permite definir operadores como | y ~ en forma de métodos, tiene conversiones implícitas, y un toque de syntax sugar que lo hace óptimo para crear DSLs (domain specific languages).
Combinator parsing viene incluido en la librería estándar de Scala, y más que un API, parece un sublenguaje. Su implementación puede resultar un tanto sesuda para el no iniciado; pero su utilización, prometo, está al alcance de cualquier programador.
Otro problema que tenían las soluciones anteriores era el acoplamiento entre el parsing y la generación de la salida. Vamos a separar las responsabilidades para que, una vez resuelto el parseo, podamos generar todas las salidas que se nos antoje.
Continuará
Otro problema que tenían las soluciones anteriores era el acoplamiento entre el parsing y la generación de la salida. Vamos a separar las responsabilidades para que, una vez resuelto el parseo, podamos generar todas las salidas que se nos antoje.
Continuará
No hay comentarios:
Publicar un comentario