informe lex y yacc

16
COMPILADORES HERRAMIENTAS LEX Y YACC LEX Es una herramienta utilizada para especificar analizadores léxicos. Suele llamarsele compilador Lex a la herramienta, y lenguaje Lex a sus especificaciones de entrada. YACC Genera un analizador sintáctico (la parte de un compilador que comprueba que la estructura del código fuente se ajusta a la especificación sintáctica del lenguaje). Como se realiza Lex genera el código C para un analizador léxico, y yacc genera el código para un parser. Tanto lex como yacc toman como entrada un archivo de especificaciones que es típicamente más corto que un programa hecho a medida y más fácil de leer y entender. Por convención, la extensión del archivo de las especificaciones para lex es .l y para yacc es .y. La salida de lex y yacc es código fuente C. Lex crea una rutina llamada yylex en un archivo llamado lex.yy.c. Yacc crea una rutina llamada yyparse en un archivo llamado y.tab.c. Estas rutinas son combinadas con código fuente C provisto por el usuario, que se ubica típicamente en un archivo

Upload: elycita

Post on 02-Apr-2015

802 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: INFORME LEX Y YACC

COMPILADORES HERRAMIENTAS LEX Y YACC

LEX

Es una herramienta utilizada para especificar analizadores léxicos. Suele llamarsele compilador Lex a la herramienta, y lenguaje Lex a sus especificaciones de entrada.

YACC

Genera un analizador sintáctico (la parte de un compilador que comprueba que la

estructura del código fuente se ajusta a la especificación sintáctica del lenguaje).

Como se realiza

Lex genera el código C para un analizador léxico, y yacc genera el código para un parser.

Tanto lex como yacc toman como entrada un archivo de especificaciones que es

típicamente más corto que un programa hecho a medida y más fácil de leer y entender.

Por convención, la extensión del archivo de las especificaciones para lex es .l y para

yacc es .y. La salida de lex y yacc es código fuente C. Lex crea una rutina llamada yylex

en un archivo llamado lex.yy.c. Yacc crea una rutina llamada yyparse en un archivo

llamado y.tab.c.

Estas rutinas son combinadas con código fuente C provisto por el usuario, que se ubica

típicamente en un archivo separado pero puede ser ubicado en el archivo de

especificaciones de yacc. El código provisto por el usuario consiste de una rutina main

que llama a yyparse, que en su momento, llama a yylex.

Diagrama lex y yacc

Compilador C

COMPILADOR

Librerías

yylex() yyparse()

Rutinas Clex.yy.c y.tab.c

lex yacc

Especific.

Lex

Especific.

Yacc

nombre_archivo.ynombre_archivo.l

Page 2: INFORME LEX Y YACC

CONSTRUCCIÓN DEL COMPILADOR

Para llegar a la construcción del compilador el usuario debe tener instalados el

compilador MINGW y el paquete de YACC.

Pasos para la instalación del paquete yacc

Asumiendo que usted ha instalado este paquete en el directorio c:\yacc, prepare su

ambiente de la siguiente manera:

Bajo la consola DOS de Windows escriba el siguiente PATH, como se ilustra en la

“figura A”.

SET PATH=c:\yacc\bin;%PATH%

SET BISON_SIMPLE=c:\yacc\bin\bison.simple

SET BISON_HAIRY=c:\yacc\bin\bison.hairy

Esta versión de YACC y LEX funcionan sin problemas con la versión del compilador

MINGW32.

Esta es una distribución mínima del compilador MINGW solo soporta el modo consola

de Windows.

Su uso básicamente es para compilar algunos ejemplos sencillos y muy útil para el

proyecto de lenguajes y compiladores. Si usted ya tiene instalada la versión completa

del mingw, no tiene sentido usar esta versión

- Su ventaja principal es su pequeño tamaño que facilita su descarga, y traslado

de una máquina a otra sin complicaciones.

Page 3: INFORME LEX Y YACC

Pasos para la instalación del paquete MgwCon

Copie la carpeta llamada "\MgwCon" en el disco local C.

En XP se puede, ejecutando el comando SET PATH=... estando en el modo consola de

Dos, ponga la ruta en el PATH : como se ilustra en la “figura B”

SET PATH=%PATH%;C:\MgwCon\Bin;

FIGURA B

Asumimos que instalo el compilador en la unidad C: aunque podría haber sido

cualquier otra.

Usted puede tener otra distribución del mingw instalada en su disco duro

(normalmente \MinGW) no habrá problemas ya que trabajarán en forma

independiente.

Uso de los archivos .l .y

Para trabajar con los archivos escritos en lex y yacc .l y .y por ejemplo con los nombres

de COM_BAS.l y COM_BAS.y.

Los dos últimos archivos (COM_BAS.L y COM_BAS.Y) cópielos a la dirección c:\yacc\bin

Page 4: INFORME LEX Y YACC

anteriormente instalada.

Bajo consola DOS coloque la dirección o ruta donde se encuentran los archivos

(COM_BAS.L y COM_BAS.Y) mediante comandos básicos como “CD”

FIGURA C

Una vez en la carpeta c:\yacc\bin escriba <lex com_bas.l> como se muetra en la “figura

C” y se creará el archivo lex.yy.c, donde lex.yy.c es una representación tabulada de un

diagrama de transiciones construido a partir de las expresiones regulares de

COM_BAS.L.

Las acciones asociadas a las expresiones regulares de COM_BAS.L son partes de código

en C y se transfieren directamente a lex.yy.c.

Ahora escriba <yacc –d com_bas.y> se especifica que –d es para generar un fichero de

cabecera llamado y.tab.h.

COM_BAS.Y constituye una especificación en yacc, luego al someter COM_BAS.Y al

compilador yacc so obtiene un programa en C llamado y.tab.c. El archivo y.tab.c es el

Page 5: INFORME LEX Y YACC

analizador sintáctico en C incluye además otras rutinas de apoyo que pudo generar el

usuario.

Copie todos los archivos (COM_BAS.L, COM_BAS.Y, lex.yy.c, y.tab.c, y.tab.h) a la

dirección c:\mgwcon\bin.

Bajo consola DOS, para generar el programa ejecutable .exe deberá escribir la

siguiente línea de código, (asegúrese de encontrarse en la carpeta c:\mgwcon\bin en

DOS).

Page 6: INFORME LEX Y YACC

Se puede cambiar el nombre del programa .exe solamente indicando otro nombre de

su elección por ejemplo gcc y.tab.c lex.yy.c –o COMPILADOR.exe.

Para nuestro ejemplo el programa ejecutable tendrá nombre com_bas.exe como se

muestra en la siguiente figura.

Nota: Si esta trabajando en modo DOS y aparece un error como el siguiente debe

volver a escribir las líneas de código del PATH. Estas se encuentra en la “figura A” y

“figura B”

Page 7: INFORME LEX Y YACC

COMPILADORES CREADOS

TRADUCTOR DE EXPRESIONES INFIJAS A POSTFIJAS

Archivo lex (.l)

%{#include "y.tab.h"

%}

%%

"EOF"|"eof" {return SALIR;}

[Dd][Ii][Vv] {return DIV;}[Mm][Oo][Dd] {return MOD;}

[A-Za-z]([A-Za-z]|[0-9])* {yylval = *yytext;printf("%s ",yytext);return VARIABLE;

}

[0-9]+ {yylval = strtol(yytext, (char **)NULL, *yytext=='0' ? 8:10);return INTEGER;

}

[0-9]+(\.[0-9]+)?(E[+\-]?[0-9]+)? {yylval = *yytext;

printf("%s ",yytext);return REAL;

}

[-()=+/*;\n] {//printf("\n\n ");return *yytext;

}

[ \t]+ ;

[~`!#%^&_'":<>?] {ECHO;yyerror("es caracter Desconocido !Error¡");

}

Page 8: INFORME LEX Y YACC

%%

int yywrap(void) { return 1;

}

---------------------%token INTEGER REAL VARIABLE DIV MOD SALIR%left '+' '-'%left '*' '/'

%{static int variables[100];static int dim[80];int i=1;int j=1;%}

%%

lineas:'\n'

| lineas declaracion '\n' ={ i=i+1; }| lineas SALIR '\n' { for(i=1;i<=80;i++)

{ if(dim[i]!=0) printf("\n!Error Sintactico --> linea %d \n",dim[i]);

}

printf("cerrando programa"); getch();

exit(1); }

| lineas error '\n' = { i=i+1;}| SALIR '\n' {printf("Cerrando programa...\n");exit(0);}|;

declaracion:expr ';' ={/*printf("%d\n",$1);*/}

| VARIABLE '=' expr ';' = { variables[$1] = $3; };expr:

VARIABLE { $$ = variables[$1]; }

Page 9: INFORME LEX Y YACC

| expr '+' expr = { printf("+ ");}| expr '-' expr = { printf("- ");}| expr '*' expr = { printf("* ");}| expr '/' expr = { printf("/ "); }| expr DIV expr = { printf("div");}| expr MOD expr = { printf("mod");}| '(' expr ')' = { $$ = $2; }| statement;

statement: INTEGER = {printf("%d ",$1); }| VARIABLE = { }| REAL = { };

%%

int yyerror(char *s){

dim[j] = i; j++; return 0;}

int main(void) { printf("\t\tUNIVERSIDAD CENTRAL DEL ECUADOR\n"); printf("\t\tDISEÑO DE COMPILADORES\n");

printf("\nFabián Silva Muñoz\n");printf("\nIngrese las expresiones \n\n");

yyparse();

return 0;}EJECUCION

CALCULADORA AVANZADA

Page 10: INFORME LEX Y YACC

Archivo lex (.l)/*PARTE DE DECLARACIONES*/%{ #include "y.tab.h" #include <string.h>

char cadena[255]; int linea = 1;%}

%%

/*PARTE DE REGLAS*/ /* */[a-z] { yylval = *yytext - 'a'; return VARIABLE; }

/* enteros */[0-9]+ { yylval = atoi(yytext); return ENTERO; }

/* nueva linea */[\n] { linea++; return *yytext; }

/* operadores */[-+()=/*] { return *yytext; }

/* otros simbolos */[;,] { return *yytext; }

/* salta espacios en blanco */[ \t] ;

/* comando print */print return CMD_PRINT;

/* cadena */\".*\" { strncpy( cadena, ++yytext, yyleng - 2 ); cadena[ yyleng - 2 ] = '\0'; return CADENA; }

/* funciones */"abs" return FUNC_ABS;"max" return FUNC_MAX;

/* cualquier otra cosa es un error */. yyerror("caracter invalido");

%%/*PARTE DE DEFINICIONES DE USUARIO*/

int yywrap(void) { return 1;

Page 11: INFORME LEX Y YACC

}

/*PARTE DE DECLARACIONES*/%token ENTERO VARIABLE CMD_PRINT CADENA FUNC_ABS FUNC_MAX FUNC_DIV%left '+' '-'%left '*' '/'%{ int sim[26]; extern char cadena[255]; extern linea;%}

%%/*PARTE DE REGLAS*/

linea: linea declaracion '\n' | ;

declaracion: expr { printf("%d\n", $1); } | VARIABLE '=' expr { sim[$1] = $3; } | CMD_PRINT CADENA { printf("%s\n",cadena); } | CMD_PRINT CADENA ';' { printf("%s",cadena); } | ;

expr: ENTERO | VARIABLE { $$ = sim[$1]; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr {

if ( $3 == 0.0 ){ printf( "Error, Divisi¢n para cero", "" );} else{ $$ = $1 / $3;}}

| '(' expr ')' { $$ = $2; } | FUNC_ABS '(' expr ')' { $$ = abs( $3 ); } | FUNC_MAX '(' expr ',' expr ')' { if ( $3 > $5 ) $$ = $3; else $$ = $5; } | expr FUNC_DIV expr { $$=$1; printf(" div "); } ;

%%/*PARTE DE DEFINICIONES DE USUARIO*/

int yyerror(char *s) {

char mensaje[100];

if ( !strcmp( s, "parse error" ) )

Page 12: INFORME LEX Y YACC

strcpy( mensaje, "Error de sintaxis" ); else strcpy( mensaje, s );

fprintf(stderr, "Error en linea %d: %s\n", linea, mensaje); printf("ha ocurrido un error\n"); getch(); return 0;}

int main(void) { printf("\t\tUNIVERSIDAD CENTRAL DEL ECUADOR"); printf("\t\tDISEÑO DE COMPILADORES"); printf("\nFabián Silva Muñoz\n"); printf("\n\nIngrese la expresion a calcular: "); yyparse(); return 0;}

EJECUTABLE

CONVIERTE DE ENTEROS A ROMANOS

Archivo lex (.y)%{#include<stdio.h>#include<ctype.h>/*#include<conio.h>*/char *ts[30]={ "I","II","III","IV","V","VI","VII","VIII","IX","X","XX","XXX","XL","L","LX","LXX","LXXX","XC","C","CC","CCC","CD","D","DC","DCC","DCCC","CM","M","MM","MMM"};void mil(int);void cien(int);void decena(int);void unidad(int);void yyerror(char *s);

%}%token NUMERO

%%expresion: NUMERO ;%%yylex(){ int c; scanf("%d",&c); while(c!=0){

if(c>999) mil(c);

Page 13: INFORME LEX Y YACC

else if(c>99) cien(c); else if(c>9) decena(c);

else unidad(c); return NUMERO;

} return c;

}

void mil(int c){ int a; a=c%1000; c=c/1000; printf("%s",ts[26+c]); if(a>99) cien(a); else if(a>9) decena(a); else unidad(a); } void cien(int c){ int a; a=c%100; c=c/100; printf("%s",ts[17+c]); if(a>9) decena(a); else unidad(a); } void decena(int c){ int a; a=c%10; c=c/10; printf("%s",ts[8+c]); unidad(a); } void unidad(int c){ if(c>0) printf("%s",ts[c-1]); else yyerror;}

void yyerror(char *s){ printf("%s", s);

}

void main(){ printf("Ingrese un nùmero: "); yyparse();/*llama a la yylex para tener otro componente lexico*/

Page 14: INFORME LEX Y YACC

getch(); }

EJECUTABLE