ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
PONTIFICIA UNIVERSIDAD CATOLICA DEL ECUADOR SEDE IBARRA Nombre: Jhampier Piedra TALLER DE COMPILADORES Utilizando la herramienta de búsqueda de la Web, Investigar los siguientes temas: Herramientas para la construcción de procesadores de lenguaje. Herramientas para la construcción de Procesadores de Lenguajes Herramienta Lenguaje Descripción Bison
C
Generador de Analizadores Sintácticos Ascendentes tipo YACC
COCO/R
C/C++
Generador de Analizadores Léxicos y Sintácticos Descendentes Recursivos
Flex
C
Generador de Analizadores Léxicos tipo Lex
Lex
C
Generador de Analizadores Léxicos
SDGLL1
exe
Sistema Detector de Gramáticas LL(1) y generador de la tabla
TS 2006
C/C++
Tipo abstracto de datos Tabla de Símbolos de uso sencillo
TS
C
Tipo abstracto de datos Tabla de Símbolos
TS-OO
C++
Tipo abstracto de datos orientado a objetos Tabla de Símbolos
exe
Visualizador de árboles sintácticos partiendo de los ficheros con la gramática y el parse pedidos en la Práctica la Práctica [versión 2.0, Windows]
VASt
C++
Visualizador de árboles sintácticos partiendo de los ficheros con la gramática y el parse pedidos en la Práctica la Práctica [versión 1.0, Linux]
YACC
C
Generador de Analizadores Sintácticos Ascendentes LR(1)
VASt
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
Aplicación de los lenguajes: Los lenguajes de programación hoy en día tienen una infinidad de aplicaciones, básicamente cualquier objeto electrónico tiene cierto grado de programación. Algunos de los más comunes son C++ y JAVA, también existe HTML, HTTP, XML, XAML y C#, este último actualmente es el más utilizado en todos los dispositivos y redes basados en MICROSOFT (Xbox 350, Windows Mobile, Windows Phone, Windows Cloud, Zune, etc.). Ya que los lenguajes de programación son informáticamente un puente entre el Hardware y el Software estos permiten que las computadoras puedan establecer conexión con un celular, una cámara o una consola portátil de videojuego. Otra de las aplicaciones de los lenguajes de programación son las matemáticas como las calculadoras, cajas registradoras, cajeros automáticos, por solo mencionar algunos ejemplos sencillos. Existen también niveles de programación mucho más complejos como los videojuegos o los pilotos automáticos de los aviones comerciales o las máquinas de juego de los casinos que siguen un patrón de probabilidad a partir de un arreglo de números al azar establecido por una programación numérica. La robótica es la combinación de mecánica, electrónica y programación, la cual en base a sensores y mecanismos sigue una serie de instrucciones algorítmicas las cuales le permiten por ejemplo a un brazo robótico montar una rueda, ajustar un tornillo o cortar un rectángulo de 3 cm cuadrados en una placa de acero. Con el avance de la tecnología los límites de la programación se vuelven cada vez más distantes. Reseña Histórica Para facilitar el trabajo, los primeros operadores de computadoras decidieron hacer un traductor para reemplazar los 0 y 1 por palabras o abstracción de palabras y letras provenientes del inglés; éste se conoce como lenguaje ensamblador. Por ejemplo, para sumar se usa la letra A de la palabra inglesa add (sumar). El lenguaje ensamblador sigue la misma estructura del lenguaje máquina, pero las letras y palabras son más fáciles de recordar y entender que los números. La necesidad de recordar secuencias de programación para las acciones usuales llevó a denominarlas con nombres fáciles de memorizar y
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
asociar:ADD (sumar), SUB (restar), MUL (multiplicar), CALL (ejecutar subrutina), etc. A esta secuencia de posiciones se le denominó "instrucciones", y a este conjunto de instrucciones se le llamó lenguaje ensamblador. Posteriormente aparecieron diferentes lenguajes de programación, los cuales reciben su denominación porque tienen una estructura sintáctica similar a los lenguajes escritos por los humanos, denominados también lenguajes de alto nivel. La primera programadora de computadora conocida fue Ada Lovelace, hija de Anabella Milbanke Byron y Lord Byron. Anabella introdujo en las matemáticas a Ada quien, después de conocer aCharles Babbage, tradujo y amplió una descripción de su máquina analítica. Incluso aunque Babbage nunca completó la construcción de cualquiera de sus máquinas, el trabajo que Ada realizó con éstas le hizo ganarse el título de primera programadora de computadoras del mundo. El nombre del lenguaje de programación Ada fue escogido como homenaje a esta programadora. Diseño y construcción de un compilador.
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
Flex y Bison Flex es un una herramienta que permite generar analizadores léxicos. A parr de un conjunto de expresiones regulares, Flex busca concordancias en un chero de entrada y ejecuta acciones asociadas a estas expresiones. Es compable 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. GNU bison es un programa generador de analizadores sintáccos de propósito general perteneciente al proyecto GNU disponible para práccamente todos los sistemas operavos, se usa normalmente acompañado de ex aunque los analizadores léxicos se pueden también obtener de otras formas.
Instalación de Flex y Bison 1. Descarga el soware disponible en el sio de la cátedra. 2. Instalar el soware en la unidad C: (para explicar a parr del punto 4 se tendrá como
hipótesis de que ex y bison han sido instalados en la ruta: C:\GnuWin32\ donde conene una subcarpeta llamada bin donde se encuentran los programas respecvos) 3. Flex y bison son aplicaciones de consola, por lo que se deberá entrar al Símbolo del sistema y
pear líneas de comando para ejecutar Flex. Una alternava 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 ex y bison se integren al conjunto de variables del entorno (esto te va a
permir llamar a ex/bison desde cualquier ubicación en la línea de comandos) debes hacer lo siguiente:
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
• Clic derecho en “Mi PC”. • Selecciona “Propiedades” • Clic en la pestaña “Opciones Avanzadas” • Presiona el botón “Variables de entorno”
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 “Modicar” (si no está hacer clic en “Nueva” y agregar PATH)
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
En la nueva ventana, escribir la ruta completa al directorio “bin” de la aplicación ex/bison. Si existe otro valor, separarlos con comas.
Aceptar los cambios y luego reiniciar el sistema operavo. 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:
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
Como se compila con Flex y Bison Para compilar en Flex y Bison seguimos los siguientes pasos. Cuando tengas listo podrás llamar a ex/bison desde el símbolo del sistema sin necesidad de ubicarte en la carpeta donde ha sido instalado ex/bison. Luego de escribir las especicaciones de ex y bison realizar lo siguiente. Si se desea invocar a ex:
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
2 Ejemplos de la creación de un compilador ulizando Flex y Bison.
/***************** Deniciones Se colocan las cabeceras, variables y expresiones regulares ******************** %{ #include
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
#include #include "sintacco.tab.h" int linea=0; %} /* Creamos todas las expresiones regulares Creamos la denición llamada DIGITO, podemos acceder esta denición usando {DIGITO}*/ DIGITO [0-9] NUMERO {DIGITO}+("."{DIGITO}+)? %% /*************** Reglas *****************/ /* Creamos las reglas que reconocerán las cadenas que acepte Nuestro scanner y retornaremos el token a bison con la funcion return. */ {NUMERO} {yylval.real=atof(yytext); return(NUMERO);} "="
{return(IGUAL);}
"+"
{return(MAS);}
"-"
{return(MENOS);}
";"
{return(PTOCOMA);}
"*"
{return(POR);}
"/"
{return(DIV);}
"("
{return(PAA);}
")"
{return(PAC);}
"\n"
{linea++;}
[\t\r\f] {} ""
{}
/* Si en nuestra entrada ene algún caracter que no pertenece a
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
las reglas anteriores, se genera un error léxico */
.
{prin("Error lexico en linea %d",linea);}
%% /* Código de Usuario Aquí podemos realizar otras funciones, como por ejemplo ingresar símbolos a nuestra tabal de símbolos o cualquier otra accione del usuario. Todo lo que el usuario coloque en esta sección se copiara al archvi lex.yy.c tal y como esta. */ Guardamos el archivo como lexico.l. Luego creamos un nuevo archivo y colocamos el siguiente código. %{ /******************** Declaraciones en C **********************/ #include #include #include extern int yylex(void); extern char *yytext; extern int linea; extern FILE *yyin; void yyerror(char *s); %} /************************ Declaraciones de Bison *************************/ /* Especica la coleccion completa de pos de datos para poder usar
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
varios pos de datos en los terminales y no terminales*/ %union { oat real; } /* Indica la produccion con la que inicia nuestra gramaca*/ %start Exp_l /* Especicacion de termines, podemos especicar tambien su po */ %token NUMERO %token MAS %token MENOS %token IGUAL %token PTOCOMA %token POR %token DIV %token PAA %token PAC /* No Terminales, que tambien podemos especicar su po */ %type Exp %type Calc %type Exp_l /* Denimos las precedencias de menor a mayor */ %le MAS MENOS %le POR DIV %% /********************** Reglas Gramacales ***********************/ Exp_l:
Exp_l Calc |Calc
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
; Calc
: Exp PTOCOMA {prin ("%4.1f\n",$1)} ;
/* con el símbolo de $$ asignamos el valor semánco de toda la acción de la derecha y se la asignamos al no terminal de la izquierda, en la siguiente regla, se la asigna a Exp. Para poder acceder al valor de los terminales y no terminales del lado derecho usamos el símbolo $ y le concatenamos un numero que representa la posición en la que se encuentra es decir si tenemos A --> B NUMERO C Si queremos usar le valor que ene el no terminal B usamos $1, si queremos usar el valor que ene NUMERO usamos $2 y así sucesivamente. */ Exp :
NUMERO {$$=$1;} |Exp MAS Exp {$$=$1+$3;} |Exp MENOS Exp {$$=$1-$3;} |Exp POR Exp {$$=$1*$3;} |Exp DIV Exp {$$=$1/$3;} |PAA Exp PAC {$$=$2;} ;
%% /******************** Codigo C Adicional **********************/ void yyerror(char *s) { prin("Error sintacco %s",s); } int main(int argc,char **argv) {
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
if (argc>1) yyin=fopen(argv[1],"rt"); else yyin=stdin; yyparse(); return 0; }
Segundo ejemplo
Fichero léxico_solo.l
%{ /* Ejemplo para una pequeña calculadora que permite trabajar con numeros enteros y reales con las operaciones básicas de suma, resta, producto, division y trigonometricas como el seno y el coseno */ #include #include int nlines=0; %} DIGITO [0-9] ID [a-zA-Z][a-zA-Z0-9_]* %% {DIGITO}+ {prin("Encontrado TKN_NUM_ENTERO: %d",atoi(yytext));} {DIGITO}+"."{DIGITO}+ {prin("Encontrado TKN_NUM_REAL: %f",atof(yytext));} "=" {prin("Encontrado TKN_ASIGN: %s",yytext);} ";" {prin("Encontrado TKN_PTOCOMA: %s",yytext);} "*" {prin("Encontrado TKN_MULT: %s",yytext);} "/" {prin("Encontrado TKN_DIV: %s",yytext);} "+" {prin("Encontrado TKN_MAS: %s",yytext);} "-" {prin("Encontrado TKN_MENOS: %s",yytext);}
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
"(" {prin("Encontrado TKN_PAA: %s",yytext);} ")" {prin("Encontrado TKN_PAC: %s",yytext);} "cos" {prin("Encontrado TKN_COS: %s",yytext);} "sen" {prin("Encontrado TKN_SEN: %s",yytext);} {ID} {prin("Encontrado TKN_ID: %s",yytext);} "\n" {nlines++;} %% void main(int argc,char **argv) { if (argc>1) yyin=fopen(argv[1],"rt"); else yyin=stdin; yylex(); prin("\nNumero lineas analizadas: %d\n", nlines); } /* para compilar ex lexico.l cc lex.yy.c -o milex -l -lm */ Fichero léxico.l (versión a enlazar con Bison)
%{ /* Ejemplo para una pequeña calculadora que permite trabajar con las operaciones básicas de suma, resta, producto, division y trigonometricas como el seno y el coseno */ #include #include #include "sintacco.tab.h" int nlines=0; %}
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
DIGITO [0-9] ID [a-zA-Z][a-zA-Z0-9_]* %% {DIGITO}+("."{DIGITO}+)? {//prin("Encontrado TKN_NUM: %f\n",atof(yytext)); yylval.real=atof(yytext); return(TKN_NUM);} "=" {//prin("Encontrado TKN_ASIGN: %s\n",yytext); return(TKN_ASIGN);} ";" {//prin("Encontrado TKN_PTOCOMA: %s\n",yytext); return(TKN_PTOCOMA);} "*" {//prin("Encontrado TKN_MULT: %s\n",yytext); return(TKN_MULT);} "/" {//prin("Encontrado TKN_DIV: %s\n",yytext); return(TKN_DIV);} "+" {//prin("Encontrado TKN_MAS: %s\n",yytext); return(TKN_MAS);} "-" {//prin("Encontrado TKN_MENOS: %s\n",yytext); return(TKN_MENOS);} "(" {//prin("Encontrado TKN_PAA: %s\n",yytext); return(TKN_PAA);} ")" {//prin("Encontrado TKN_PAC: %s\n",yytext); return(TKN_PAC);} "cos" {//prin("Encontrado TKN_COS: %s\n",yytext); return(TKN_COS);} "sen" {//prin("Encontrado TKN_SEN: %s\n",yytext); return(TKN_SEN);} {ID} {//prin("Encontrado TKN_ID: %s\n",yytext); return(TKN_ID);} "\n" {nlines++;} .
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
%% /******** Para el lexico solo void main(int argc,char **argv) { if (argc>1) yyin=fopen(argv[1],"rt"); else yyin=stdin; yylex(); prin("\nNumero lineas analizadas: %d\n", nlines); } *******/ /* para compilar ex lexico.l cc lex.yy.c -o milex -l -lm */ Fichero sintacco.y (Bison)
%{ /* Ejemplo para una pequeña calculadora que permite trabajar con numeros enteros y reales con las operaciones básicas de suma, resta, producto, division y trigonometricas como el seno y el coseno */ #include #include #include extern int yylex(void); extern char *yytext; extern int nlines; extern FILE *yyin; void yyerror(char *s);
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
%} %union { oat real; } %start Calculadora %token TKN_NUM %token TKN_ASIGN %token TKN_PTOCOMA %token TKN_MULT %token TKN_DIV %token TKN_MAS %token TKN_MENOS %token TKN_PAA %token TKN_PAC %token TKN_COS %token TKN_SEN %token TKN_ID %type Calculadora %type Expresion %le TKN_MAS TKN_MENOS %le TKN_MULT TKN_DIV %% Calculadora : TKN_ID { prin("El valor de %s es: ", yytext);} TKN_ASIGN Expresion TKN_PTOCOMA { prin("%5.2f\n", $4); } ; Expresion : TKN_NUM {$$=$1;}| Expresion TKN_MAS Expresion {$$=$1+$3;}| Expresion TKN_MENOS Expresion {$$=$1-$3;}| Expresion TKN_MULT Expresion {$$=$1*$3;}| Expresion TKN_DIV Expresion {$$=$1/$3;} |
ESCUELA DE INGENIERIA- SISTEMAS COMPILADORES
TKN_PAA Expresion TKN_PAC {$$=$2;}| TKN_COS TKN_PAA Expresion TKN_PAC {$$=cos($3);}| TKN_SEN TKN_PAA Expresion TKN_PAC {$$=sin($3);}; %% void yyerror(char *s) { prin("Error %s",s); } int main(int argc,char **argv) { if (argc>1) yyin=fopen(argv[1],"rt"); else yyin=stdin; yyparse(); prin("FIN del Analisis. Entrada CORRECTA\n"); prin("Numero lineas analizadas: %d\n", nlines); return 0; } /* para compilar bison -d sintacco.y ex lexico.l cc lex.yy.c sintacco.tab.c -o analizador -l -lm */