Upload
josemanuel486
View
1.363
Download
23
Embed Size (px)
DESCRIPTION
UNIVERSIDAD DE SANCARLOS DE GUATEMALAOrganización de lenguajes y Compiladores 1Manual Flex y Bison con QtPrimeros pasosCreado por: José Manuel González AlvarezINTRODUCCIONEl siguiente manual presenta una introducción de cómo utilizar conjuntamente Bison Flex y Qt, se presenta una introducción ambas herramientas, después se explica la instalación de las misma sobre el sistema operativo Linux, y se concluye con un ejemplo practico para observar como se utilizan juntas estas herramientas.
Citation preview
UNIVERSIDAD DE SANCARLOS DE GUATEMALA
Organización de lenguajes y Compiladores 1
Creado por: José Manuel González
Alvarez
Manual Flex y Bison con Qt Primeros pasos
INTRODUCCION
El siguiente manual presenta una introducción de cómo utilizar conjuntamente
Bison Flex y Qt, se presenta una introducción ambas herramientas, después se explica
la instalación de las misma sobre el sistema operativo Linux, y se concluye con un
ejemplo practico para observar como se utilizan juntas estas herramientas.
Notas del Autor
Este manual solo es una inicialización a esta tecnología así que no se
profundiza, tanto en la sintaxis de la herramienta y se supone un conocimiento mínimo
del lector.
El objetivo primordial, es despertar el interés del lector hacia eta tecnología y
que le sirva como una guía inicial, para uso.
Flex
Que es: Flex es una herramienta para generar analizadores léxicos: programas que reconocen
patrones en un texto. Flex lee los ficheros de entrada dados, o la entrada estándar si no se le
ha indicado ningún nombre de fichero, con la descripción de un escáner a generar. La
descripción se encuentra en forma de parejas de expresiones regulares y código C,
denominadas reglas. Flex genera como salida un fichero fuente en C.
Instalación: Puede descargar los paquetes de instalación de la siguiente dirección.
http://flex.sourceforge.net/
A continuación se presenta una instalación desde el sistema operativo Linux utilizando la
distribución Ubuntu.
Primero abra el repositorio (Sistema -> Administración -> Gestor de paquetes Synaptic) y
escriba en el buscador flex, marque el paquete flex como se ve en la imagen.
De clic en aplicar y espere a que termine la instalación. Después abra un terminal y escriba flex
– V le tiene que salir algo parecido a la imagen, listo tiene instalado Flex.
Bison
Que es:
Bison es un generador de analizadores sintácticos propósito general a partir de una
gramática libre de contexto clasificada como LALR (1) este analizador es generado en
código c.
Los analizadores generados por Bison pueden ser utilizados para construir lenguajes
desde pequeños lenguajes como los utilizados en calculadoras de Escritorio, hasta
lenguajes complejos de programación.
Instalación: Puede descargar los paquetes de instalación de Bison de la siguiente dirección
http://www.gnu.org/software/bison/.
A continuación se presenta una instalación desde el sistema operativo Linux utilizando la
distribución Ubuntu.
Primero abra el repositorio (Sistema -> Administración -> Gestor de paquetes Synaptic) y
escriba en el buscador bison, marque el paquete bison como se ve en la imagen.
De clic en aplicar y espere a que termine la instalación. Después abra un terminal y escriba
bison - -version le tiene que salir algo parecido a la imagen, listo tiene instalado bison.
Descripción del archivo de entrada: Estructura general de un archivo bison.
%{
Prólogo
%}
Bison declarations
%%
Grammar rules
%%
Epílogo
Prologo:
En esta área van los include y métodos que el programador considere conveniente escribir,
todo en esto en el lenguaje c.
Bison declarations:
Aquí se incluye las opciones que da bison, como la declaración de terminales y no terminales
que usara en la gramatica.
Si se requiere usar un tipo de dato para los terminales y no terminales se usa esta opción
donde se declara, los tipos que se requiera %union{tipodato id;…así sucesivamente} ejemplo
%union{int Str;}
Para declarar un terminal
%token<Tipodato> id; ejemplo %token<Str> nEntero;
Grammar rules:
En esta area se localizan la reglas gramaticales que regiran a nuestro analizador
Sintaxis general;
Noterminal: reglas
Ejemplo:
RESULTADO: RESULTADO Nmas RESULTADO
También se pueden colocar acciones
RESULTADO: RESULTADO Nmas RESULTADO{/*código c. */}
Utilizar Bison y Flex en Qt
La mejor manera de aprender esto es con un ejemplo, así que realizaremos una calculadora
con operaciones básicas suma, resta multiplicación y división, usando Qt, bison y flex.
Objetivo: Aprender a usar flex y bison con qt atraves de un ejemplo sencillo.
Aprender a usar QFileDialog de Qt, para cargar archivos a bison y ejecutar de ahí.
Descripción general del ejemplo: Se carga un archivo de entrada con una cadena de operaciones aritméticas ejemplo: “5+5*4”,
este se presenta en un caja de texto, después se da clic en el botón calcular y en una caja de
texto diferente, se presenta los resultados, también se puede cambiar los datos en la caja de
texto y darle a calcular automáticamente guarda los cambios y hace los cálculos.
Interfaz del programa.
Cargando el archivo:
Creando ejemplo paso a paso:
Crear el proyecto en qt
Creando los archivos de analizador léxico y sintactico:
Se da clic derecho sobre el proyecto y en add new, saldrá un cuadro de dialogo como el de la
imagen de abajo se da clic en choose se coloca el nombre y listo.
Nuestro archivo léxico se llama scan.l y el sintactio parser.y
En anexos se coloco el código de el analizador sintatico y lexico.
Compilando los archivos scan y parser. Abra un terminal sitúes en la carpeta donde esta situado sus archivos.
Para bison escribes lo siguiente:
Bison –o parser.cpp --defines=parser.h parse.y –v
Como se muestra en la imagen.
Para flex: Flex –header –file=scanner.h –o scanner.cpp scan.l
Para una lista completa de las opciones sobre flex y bison, escribe en consola, flex --help o bison –help
Añadiendo los archivos:
Ahora das clic derecho sobre la carpeta source y Header, selecciona la opción add Existing,
Vas a tu carpeta donde generaste tus archivos bison y flex, en nuestro caso fue la misma
carpeta de proyecto, te recomiendo que lo hagas ahí. Seleccionas el archivo, el .h es para la
carpeta Header y el .cpp es para la carpeta Sources. Has lo mismo para los cuatro archivos dos
.cpp y dos .h cada par corresponde a tu analizador léxico y sintáctico.
Ahora en tu principal agrega lo siguiente en nuestro caso se llama inicio.
Este metodo agrega el archivo que se analizara extern int yyrestart(FILE* archivo); Este método hace el analisis extern int yyparse(); Este metodo agrega nuestro editor donde se mostraran los resultados extern void setEditor(QTextEdit* editor); Este metodo agrega nuestro editor donde se mostraran los errores extern void setTexEdit(QTextEdit* edit1);
Nota: los dos primeros métodos siempre se deben agregar los otros fueron creados por mí
para imprimir el resultado del análisis.
ANEXO Les dejo el código de el archivo sca.l, parse.y respectivamente, así como parte de código que considero interesante. Guarda un archivo, recibe como parámetro el nombre del archivo, El contenido que se gurdara lo extrae de la caja de texto bool inicio::saveFile( QString fileName) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { return false; } QTextStream out(&file); #ifndef QT_NO_CURSOR QApplication::setOverrideCursor(Qt::WaitCursor); #endif out << ui->pantalla->toPlainText();//guardando contenido #ifndef QT_NO_CURSOR QApplication::restoreOverrideCursor(); #endif return true; } abre un archivo, recibe como parámetro el nombre del archivo, Este método es llamado a pulsar el botón abrir de la aplicación. void inicio::on_pushButton_clicked() { nameFile=QFileDialog::getOpenFileName(this,tr("abrir"),tr("/home/jose/Escritorio"),tr("Archivo de texto (*.txt)")); QString file= nameFile; if(!file.isNull()){ ui->pantalla->setText(""); QFile archivo(file); if (!archivo.open(QIODevice::ReadOnly | QIODevice::Text)) return; QTextStream in(&archivo); while (!in.atEnd()) { QString line = in.readLine(); ui->pantalla->append(line); } } } Este método llama al analizador. void inicio::on_bcalcular_clicked() { setEditor(ui->textEdit); //se agrega el editor donde se dan los resultados setTexEdit(ui->textEdit); //se agrega el editor donde se mostran los errores //en nuestro caso es el mismo editor.
//la variable nameFile tiene guardado el nombre del documento analizar, que se abrió con el QFileDialog, el método toLati1().contsData(), retorna un *char, para compatibilidad con el método fopen FILE* input = fopen(nameFile.toLatin1().constData(), "r" ); if (input!=NULL){ saveFile(nameFile); yyrestart(input); yyparse(); } } Archivo scan.l: %option noyywrap %option yylineno %{ #include "parser.h" #include <iostream> #include <QString> #include <QTextEdit> QTextEdit* salida; extern void setTexEdit(QTextEdit* edit1); void setTexEdit(QTextEdit* edit1) { salida= edit1; } void ImprimirError(QString val) {salida->append(val); } %} blanco1 [\t\n]* digito [0-9] Numero_Entero {digito}+ Numero_Decimal {digito}+"."{digito}+ %% {blanco1} {/*Se ignoran los blancos*/} [+] {return (Nmas); } [-] {return (Nmenos); } [*] {return (Npor); } \/ {return (Ndiv); } [(] {return (Nparen); } [)] {return (Ncparen); } {Numero_Entero} {return (Nent); } {Numero_Decimal} {return (Nfloat); } . {ImprimirError(QString("Error Lexico en Fila: %1 en %2").arg(yylineno).arg(yytext));} %%
Archivo parser.y: %{ #include "scanner.h" #include <iostream> #include <QString> #include <QTextEdit> #include <QList> extern int yylineno; extern char *yytext; extern void ImprimirError(QString val); extern void setEditor(QTextEdit* editor); QTextEdit* edit; void imprimir(QString val) { edit->setText(val); } void setEditor(QTextEdit* editor) { edit=editor; } int yyerror(const char* mens) { ImprimirError(QString("Error Sintactico en Fila: %1, en %2").arg(yylineno).arg(yytext)); return 0; } %} %union{ double STR2; } %token<STR2> Nmas %token<STR2> Nmenos %token<STR2> Npor %token<STR2> Ndiv %token<STR2> Nparen %token<STR2> Ncparen %token<STR2> Nent %token<STR2> Nfloat %type<STR2> RESULTADO %left Nmas Nmenos %left Npor Ndiv
%% INICIO: RESULTADO {imprimir("Resultado: "+QString::number($<STR2>1))} ; RESULTADO: RESULTADO Nmas RESULTADO {$<STR2>$ = $<STR2>1+$<STR2>3} | RESULTADO Nmenos RESULTADO {$<STR2>$ = $<STR2>1-$<STR2>3} | RESULTADO Npor RESULTADO{$<STR2>$ = $<STR2>1*$<STR2>3} | RESULTADO Ndiv RESULTADO {$<STR2>$ = $<STR2>1/$<STR2>3} | Nparen RESULTADO Ncparen {$<STR2>$ = $<STR2>2} | Nent {$<STR2>$ = $<STR2>1} | Nfloat {$<STR2>$ = $<STR2>1}; %%