Bueno, hoy quiero extender un poco lo que es el uso de flex y bison en Qt4, gracias a la petición de un lector. En esta ocasión lo que se quiere es poder conocer el valor semántico de un identificador, ejemplo:
int variableEntera;
Con código anterior ademas de saber que es una variable, queremos saber cual es su nombre, en este caso “variableEntera”.
Así como el primer artículo, he investigado bastante para encontrar la mejor manera de hacer eso, pero no hay mucha info, así que lo que les propongo me lo invente según lo que pude observar a la hora de estar trabajando con estas herramientas.
Proyecto de de ejemplo: QtFlexBison2.tar.gz
En el archivo scanner.l estan las reglas del analizador léxico. Para generar el código en C++ ejecutamos lo siguiente en la carpeta donde esta el archivo:
flex -d -o scanner.cc scanner.l
Ese comando nos crea el archivo scanner.cc.
En el archivo parser.y estan las reglas del analizador sintactico y semantico. Para generar el código C++ ejecutamos lo siguiente en la carpeta donde esta el archivo:
bison++ -d -hparser.h -o parser.cc parser.y
Ese comando nos crear dos archivos: parser.cc y parser.h
Ahora abrimos el archivo QtFlexBison.pro con Qt Creator y lo compilamos.
Explicación:
El programa consiste en poder reconocer un grupo de variables en un grupo especifico, no tiene nada que ver con algún lenguaje, solo me lo invente para ejemplificar el caso.
La estructura del texto es el siguiente:
| principal
{ grupo:nombre { var:uno var:dos } grupo:otro_grupo { var:tres var:cuatro var:cinco var:seis } } Tenemos 2 grupos, cada uno con sus variables. El programa es capaz de recorrer el texto, saber cuales son los grupos y que variables tienen. Las salida del programa es el siguiente:
|
Con esto podemos saber el nombre del grupo y que variables tiene con su respectivo nombre.
Las reglas semánticas se encuentran en el archivo parser.y, en ella se encuentra la manera de poder obtener el nombre del identificador. Algo que quiero resaltar es la manera que se van cumpliendo las reglas, si no se entiende eso no podemos ir obteniendo los valores. En este ejemplo el orden en que se cumplen las reglas es el siguiente:
(Las reglas tienen qDebug() para que se vea el orden en que se cumplieron las reglas)
Si se dan cuenta primero encontramos el nombre del grupo o variable y hasta después se cumple la regla que le pertenece, eso hace que tengamos que guardar el nombre en algún lado hasta que se cumpla la regla. Para ese fin use un pila, en la que se ingresan los identificadores y cuando se vayan cumpliendo reglas se van sacando. ejemplo:
Imaginemos
grupo: uno{
var: variable_uno
var: variable_dos
}
La pila se llena asi:
se encuentra el nombre del grupo: uno pila: uno
se encuentra el nombre del la var1: variable_uno uno
pila: variable_uno
se cumple la regla de variable: se saca de la pila pila: uno
se encuentra el nombre del la var2: variable_dos uno
pila: variable_dos
se cumple la regla de variable 2: se saca de la pila pila: uno
se cumple la regla de grupo: se saca de la pila pila:
Como se puede ver se tiene que estar guardando el nombre de los elementos que queremos hasta que se cumpla con la regla que le corresponde.
Es la manera que encontrado para hacer esto, si alguien tiene una mejor manera de hacerlo que nos haga el favor de compartirlo para que aprendamos todos.
Espero que les sirva. =)
