1. PONTIFICIA UNIVERSIDAD CATOLICA DEL ECUADOR SEDE IBARRA
NOMBRE: Félix López
CURSO: 5 Nivel Sistemas
FECHA:28 – 05 - 2013
TALLER
Herramientas para la construcción de procesadores de lenguaje.
Suelen usarse herramientas de desarrollo de software convencionales (control de traza,
puntos de ruptura, depuradores, etc.). Sin embargo se pueden añadir a estas herramientas
otras más especializadas que se han denominado con diferentes nombres: compilador de
compiladores, generadores de compiladores, sistemas de escritura de traductores:
Generadores de analizadores léxicos: basada en el uso de expresiones regulares,
generan automáticamente el código fuente para el análisis léxico a partir de una
especificación de los tokens. El generador es un autómata finito. La más usada es
lex, incorporada en el sistema operativo UNÍX. Existen versiones para PC.
Generadores de analizadores sintácticos: Construyen el código fuente del
analizador sintáctico a partir de la especificación de la gramática del lenguaje
fuente. La más usada yacc incluida en UNÍX. También existen versiones para PC.
Analizadores de gramáticas: dada una gramática especificada formalmente,
verifican si es de un determinado tipo o no. Normalmente se utilizan para verificar
las gramáticas LL(k) y LR(k).
Máquinas de traducción dirigida por sintaxis: Producen un conjunto de rutinas
que recorren el árbol sintáctico y generan código intermedio. Asocian una o más
traducciones a cada nodo sintáctico.
Generadores automáticos de código: Trabajan con un conjunto de reglas que
permiten la traducción del código en lenguaje intermedio al lenguaje objeto. Las
reglas suelen remplazar instrucciones de código intermedio por patrones que
contienen las instrucciones equivalentes de la máquina objeto.
Analizadores de flujo: Suministran la información necesaria para realizar las
optimizaciones de código.
Reseña histórica y Aplicación de los lenguajes algorítmicos
Al igual que los idiomas sirven de vehículo de comunicación entre los seres humanos,
existen lenguajes que realizan la comunicación entre los seres humanos y las computadoras.
Estos lenguajes permiten expresar los programas o el conjunto de instrucciones que el
operador humano desea que la computadora ejecute.
2. Los lenguajes de computadoras toman diferentes formas; los de las primeras computadoras,
como la ENIAC y la EDSAC, se componían en el lenguaje real de las máquinas mismas. La
dificultad de programar las máquinas de esta manera limitaba drásticamente su utilidad y
proporcionaba un fuerte incentivo para que se desarrollaran lenguajes de programación más
orientados hacia la expresión de soluciones con la notación de los problemas mismos.
Los primeros lenguajes de programación se conocieron como Lenguajes Ensambladores,
un ejemplo es: TRANSCODE, desarrollado para la computadora FERUT. En los lenguajes
ensambladores se define un código especial llamado mnemónico para cada una de las
operaciones de la máquina y se introduce una notación especial para especificar el dato con
el cual debe realizarse la operación.
A mediados de los años 60's aparecieron los primeros lenguajes de propósito general como
FORTRAN, FORTRAN IV, ALGOL, COBOL, BASIC, PL/I, ADA, C,C++, PASCAL, etc.
pero el desarrollo de nuevas tecnologías, tanto en arquitectura de computadoras como en
lenguajes de programación, continúa a paso acelerado, cada vez con mayor velocidad, el
panorama está cambiando de una etapa de sistemas y lenguajes especialmente desarrollados
para aplicaciones individuales. Los lenguajes de programación actuales son los conocidos
como Lenguajes visuales, como por ejemplo Visual Fox, Visual Basic, Visual C.
Diseño y construcción de un compilador.
Diseño
Construcción
3. Las herramientas Flex y Bison
Flex
Flex es un una herramienta que permite generar analizadores léxicos. A partir de un
conjunto de expresiones regulares, Flex busca concordancias en un fichero de entrada y
ejecuta acciones asociadas a estas expresiones. Es compatible casi al 100% con Lex, una
herramienta clásica de Unix para la generación de analizadores léxicos, pero es un
desarrollo diferente realizado por GNU bajo licencia GPL.
Como se instala Flex y Bison
1. Descarga el software disponible en el sitio de la cátedra.
2. Instalar el software en la unidad C: (para explicar a partir del punto 4 se tendrá como
hipótesis de que flex y bison han sido instalados en la ruta: C:GnuWin32 donde contiene
una subcarpeta llamada bin donde se encuentran los programas respectivos)
3. Flex y bison son aplicaciones de consola, por lo que se deberá entrar al Símbolo del
sistema y tipear líneas de comando para ejecutar Flex. Una alternativa es crear un archivo
de proceso por lotes (*.bat) que contenga las líneas de comando para la ejecución de Flex y
Bison y/o la compilación del archivo generado.
4. Si deseas que flex y bison se integren al conjunto de variables del entorno (esto te va a
permitir llamar a flex/bison desde cualquier ubicación en la línea de comandos) debes hacer
lo siguiente:
• Clic derecho en “Mi PC”.
• Selecciona “Propiedades”
• Clic en la pestaña “Opciones Avanzadas”
• Presiona el botón “Variables de entorno”
4. • En la ventana de variables de entorno, ubicarse en la sección “Variables del sistema”
luego haz clic en PATH y luego en el botón “Modificar” (si no está hacer clic en “Nueva” y
agregar PATH)
• En la nueva ventana, escribir la ruta completa al directorio “bin” de la aplicación
flex/bison. Si existe otro valor, separarlos con comas
• Aceptar los cambios y luego reiniciar el sistema operativo.
5. Si deseas instalar un compilador de C como MinGwin, deberás integrar la ruta de acceso
al compilador a las variables de entorno para facilitar la llamada al programa.
Por ejemplo si se instaló MingWin en “C:Mingw” y dentro de la carpeta “bin” se
encuentra
“gcc.exe” que es el ejecutable, entonces de deberá agregar (análogo a los pasos anteriores)
lo siguiente:
5. 6. Cuando tengas listo podrás llamar a flex/bison desde el símbolo del sistema sin
necesidad de ubicarte en la carpeta donde ha sido instalado flex/bison.
Compilación y ejecución de un programa Flex
Al ejecutar el comando flexnombre_fichero_fuente se creará un fichero en C llamado
“lex.yy.c”. Si se compila este fichero con la instrucción “gcclex.yy.c –lfl –o
nombre_ejecutable” (-lfl indica enlazar con la biblioteca de flex) se obtendrá como
resultado un fichero ejecutable llamado nombre_ejecutable).
Una vez se ha creado el fichero ejecutable se puede ejecutar directamente. Flex esperará
que se introduzca texto por la entrada estándar (teclado) y lo analizará cada vez que se
pulse el retorno de carro. Para terminar con el análisis normalmente hay que pulsar
<CTRL>-D. Para poder probarlo con entradas más largas, lo más sencillo es crear archivos
de texto y usar redirecciones para que el ejecutable lea estos ficheros como entrada a
analizar. Por ejemplo si hemos creado un analizador llamado prueba1 y un fichero de texto
con datos para su análisis, llamado entrada.txt, podemos ejecutar $prueba1 <entrada.txt.
Si se quiere ejecutar algún código al final de un análisis de Flex (para mostrar resultados
por ejemplo) hay
al menos dos opciones:
%%
reglas...
%%
main() {
yylex();
código a ejecutar al final del análisis
}
o bien
6. %%
reglas...
%%
yywrap() {
código a ejecutar al final del análisis
return 1;
}
Bison
Bison es un generador de analizadores sintácticos de propósito general que convierte una
descripción para una gramática independiente del contexto (en realidad de una subclase de
éstas, las LALR) en un programa en C que analiza esa gramática. Es compatible al 100%
con Yacc, una herramienta clásica de Unix para la generación de analizadores léxicos, pero
es un desarrollo diferente realizado por GNU bajo licencia GPL. Todas la gramáticas
escritas apropiadamente para Yacc deberían funcionar con Bison sin ningún cambio.
Usándolo junto a Flex esta herramienta permite construir compiladores de lenguajes.
Compilación y ejecución de un programa Bison
Al ejecutar el comando bisonnombre_fuente.y se crea un fichero en C llamado
nombre_fuente.tab.c. Por compatibilidad con Yacc, existe la opción –y que fuerza a que el
archivo de salida se llame y.tab.c. A partir de ahora supondremos que se usa siempre esta
opción para facilitar la escritura de este documento. Otra opción útil es laopción –d, que
genera el archivo con las definiciones de tokens que necesita Flex (si se ha usado la opción
–y, el archivo se llamay.tab.h). Este archivo y.tab.hnormalmente se incluye en la sección de
declaraciones del fuente de Flex (ver el ejemplo de la sección anterior). El fichero y.tab.c se
puede compilar con la instrucción gccy.tab.c. Los pasos para usar conjuntamente Flex y
Bison serán normalmente:
1. bison -yd fuente.y
2. flexfuente.l
3. gccy.tab.clex.yy.c –lfl –o salida
Estos pasos generan un ejecutable llamado salida que nos permite comprobar qué palabras
pertenecen al lenguaje generado por la gramática descrita en el fichero Bison. Si se
7. compilan los ejemplos dados en la sección anterior y se ejecuta el fichero salida, podemos
escribir una expresión válida:
var1 := var2 + 5
y cuando pulsemos <Return>bison no dará ningún error, señal de que la palabra pertenece
al lenguaje de las expresiones correctas, sin embargo si escribimos algo que no es una
expresión válida:
var1 := var2 ++ 34
al pulsar <Return>bison nos da un “parse error” (o un error de sintaxis) que nos dice que la
palabra no pertenece al lenguaje.
EJEMPLO
%name Parser
%define LSP_NEEDED
%define MEMBERS
virtual ~Parser() {}
private:
yyFlexLexerlexer;
%define LEX_BODY {returnlexer.yylex();}
%define ERROR_BODY {cerr<<"error encountered at line: "<<lexer.lineno()<<" last
word parsed:"<<lexer.YYText()<<"n";}
%header{
#include <ostream>
#include <fstream>
#include <FlexLexer.h>
usingnamespacestd;
%}
%union {
inti_type;
}
%token UNKNOWN
%token <i_type> NUMBER
%type <i_type> number
%start number
%%
number
: NUMBER { $$ = atoi(lexer.YYText()); cout<<"Parser value "<< $$ <<endl;}
;
%%