Documente Academic
Documente Profesional
Documente Cultură
Objetivo y Temas Objetivo Disear e implementar un sistema que realice las funciones de un intrprete y/o compilador. Temas 4.1 Intrpretes: caractersticas y componentes 4.2 Compiladores: caractersticas y componentes. 4.3 Diferencias entre intrpretes y compiladores. 4.4 Diseo e Implementacin de los componentes de un compilador y/o un intrprete.
4.4.1 Analizador lxico, sintctico y semntico 4.4.2 Generacin de Cdigo objeto y ejecutable
2
4.4 Diseo e Implementacin de los componentes de un compilador y/o un intrprete. La implementacin de un compilador puede hacerse usando dos alternativas: Implementacin automtica
Especificacin de los patrones de la gramtica Uso de LEX y YACC para el lenguaje C (FLEX y BISON ms modernos y eficientes, JFLEX/Cup para Java)
Implementacin manual
Codificacin con estructuras condicionales (if, case, )
ANALIZADOR LXICO Programa Fuente = Serie de Smbolos Los smbolos representan las construcciones del lenguaje
Variables, etiquetas, palabras reservadas, constantes, operadores
El analizador lxico identifica los significados de estas construcciones Lee el programa fuente carcter a carcter Los compara con patrones que representan unidades sintcticas primarias o tokens.
5
Cada token pueden tener asociado uno o varios atributos Ejemplo: Un atributo de un token puede ser un puntero a la tabla de smbolos o un puntero a la tabla de constantes.
6
Ejemplo 1
posicin := principal + velocidad * 60
IDENT ASIGNACION IDENT MAS IDENT POR ENTERO
Funciones Complementarias
Ignorar, del programa fuente los comentarios, espacios en blanco y tabuladores. Reconocer las palabras reservadas del lenguaje. Reconocer las variables y asignarles una posicin en la tabla de smbolos. Relacionar mensajes de error con el nmero de lnea en el que aparecen. 8
Tokens:
Son los componentes lxicos generados por el analizador lexicogrfico
Atributos:
Son informacin adicional para cada componente lxico que sern utilizadas en el anlisis semntico y/o en la fase de sntesis (ej. Lexema, Tipo, Valor, Lnea). Depende del token
10
Ejemplo 2
Expresiones Regulares a*(b | c)+ L1 = {w : w=a*(b | c)+}
bccbcbccbc abbbccc abbcbcccbbc
(0-9)*.(0-9)+
0.236425 3567.45627 .753473 5.0
L2 = {w: w=(0-9)*.(0-9)+}
a* 0 o ms a (b | c) b o c c+ 1 o ms c 0-9 0 1 2 9
11
Ejemplo 3
12
13
Implementacin de analizador lexicogrfico con LEX Acepta una especificacin del lenguaje de programacin mediante un conjunto de expresiones regulares A cada expresin regular se le puede asociar cdigo C que se ejecutar cuando se identifique el correspondiente lexema en el programa de entrada Genera un programa en C (yylex) que reconoce dichas expresiones regulares Si se usa conjuntamente con YACC los tokens identificados se pasan directamente al analizador sintctico.
14
Ejemplo 4
Programa para borrar de la entrada todos los espacios en blanco y todos los tabuladores del final de lnea:
%% [ \t]+$ ;
%% Indica el inicio de las rdenes
Expresin Regular: Una o ms (+) apariciones del espacio en blanco ( ) o tabulador (\t) antes del final de la lnea ($) Accin: No se hace nada si est al final Qu se hace con el resto de los caracteres?
Se pasan todos directamente a la salida
15
16
17
Ejemplo 5
rdenes:
%% Integer printf(Localizada palabra reservada INT); Float printf(Localizada palabra reservada FLOAT);
19
Ejemplo 6
Programa que cambia palabras de la ortografa britnica a la ortografa americana
%% colour mechanise petrol printf(color); printf(mechanize); printf(gas);
21
[a-z0-9<>_]
Cualquier carcter desde la a a la z o un dgito del 0 al 9, o < o > o _
[-+0-9]
Cualquier dgito o los signos - y + Como - es un operador para incluirlo como carcter debe ir al principio de la clase de caracteres
[^abc]
Todos los caracteres excepto a, b y c
22
a+
1 o ms repeticiones del carcter a
[A-Za-z][A-Za-z0-9]*
Identificadores que empiezan por una letra (mayscula o minscula) y siguen por 0 o ms letras o dgitos
23
24
ab/cd
Reconoce ab pero slo si va seguido de cd.
ab$
Reconoce ab pero slo si est al final de lnea Es equivalente a ab/\n
^ab
Reconoce ab pero slo si se encuentra al comienzo de lnea
25
Acciones LEX
Accin por defecto
Copiar los literales de la entrada a la salida Se realiza por defecto con todos los literales que no coinciden con ninguna expresin regular Cuando se usa LEX con YACC hay que asegurarse que todos los literales coinciden con alguna expresin regular
Accin nula
Se descarta la entrada de datos y no se pasa nada a la salida Ejemplo:
[ \t\n] ;
26
Acciones LEX
Conocer el lexema que se ha reconocido
Lex deja este texto en una matriz de caracteres llamada yytext Ejemplo:
[a-z]+ printf(%s, yytext);
Alternativa:
[a-z]+ ECHO;
27
Cualquier definicin que comience en la columna 1 define literales de sustitucin del LEX
Se utilizan para simplificar la definicin de las rdenes Formato: nombre interpretacin
El nombre tiene que empezar por una letra
29
Ejemplo 7
Seccin de definiciones
D E [0-9] [DEde][-+]?{D}+
Seccin de rdenes
%% {D}+ {D}+.{D}*({E})?| {D}*.{D}+({E})?| {D}+{E} printf(integer);
printf(real);
30
LEX y YACC
Para utilizar de forma conjunta LEX y YACC cada orden LEX debe acabar con:
return(token); Se le indica al YACC el token ledo
31
Ejercicio 1
Construir un analizador lxico que sea capaz de reconocer sentencias de la forma: nuevo := viejo * RAZON + 2
Los identificadores tienen que empezar por una letra Los nmeros pueden ser enteros o reales Las operaciones vlidas son la de +, -, * y / No puede haber mas de un 0 a la izquierda de un nmero La salida ser:
IDENT ASIGNACION IDENT POR IDENT MAS ENTERO
32
Solucin ejercicio 1
%% [a-zA-Z][0-9a-zA-Z]* (0|[1-9][0-9]*) (0|[1-9][0-9]*)\.[0-9]* "+ ":=" "-" "* "/ " \t \n . %% int main() { yylex(); } { printf(" IDENT "); } { printf(" ENTERO "); } { printf(" REAL "); } { printf(" MAS "); } { printf(" ASIGNACION "); } { printf(" MENOS "); } { printf(" POR "); } { printf(" DIV "); } ; ; ECHO; { printf(" Caracter inesperado: %c",yytext[0]); }
33
Ejercicio 2
Modificar el analizador anterior para que acepte sentencias condicionales de la forma:
IF (x==5) THEN var := 4 ENDIF
Usar como operadores lgicos slo == Las palabras claves del lenguaje se pueden escribir tanto en minsculas como en maysculas
IF, if, If, iF Todas representan el inicio de una sentencia condicional
34
Solucin Ejercicio 2
%% [If][fF] [Ee][Nn][Dd][If][Ff] [Tt][Hh][Ee][Nn] [a-zA-Z][0-9a-zA-Z]* (0|[1-9][0-9]*) (0|[1-9][0-9]*\.[0-9]*) "+" ":=" "-" "*" "/" "==" [ \t] [\n\(\)] . %% int main() { yylex(); } { printf(" IF "); } { printf(" ENDIF "); } { printf(" THEN "); } { printf(" IDENT "); } { printf(" ENTERO "); } { printf(" REAL "); } { printf(" MAS "); } { printf(" ASIGNACION "); } { printf(" MENOS "); } { printf(" POR "); } { printf(" DIV "); } { printf(" IGUAL_A ");} ; ECHO; { printf(" Caracter inesperado: %c",yytext[0]); }
35
Ejercicios 3,4,5 y 6
3. Escribir un analizador lxico que reciba como entrada un texto y muestre como salida el nmero de caracteres, el nmero de palabras y el nmero de lneas que hay en el texto 4. Escribir un analizador lxico para cifrar un texto de entrada invirtiendo el orden de las letras de cada palabra 5. Modificar el programa anterior para que cifre todo menos los nmeros, que deben mantenerse en el orden en el que aparecen 6. Modificar el programa anterior para que invierta lnea a lnea y no palabra a palabra
36
Solucin ejercicio 3
%{ #include <stdlib.h> static unsigned ncaracteres = 0; /* nmero de caracteres*/ static unsigned npalabras = 0; /* nmero de palabras*/ static unsigned nlineas = 0; /* nmero de lineas*/ %} %% \n ncaracteres += 2, ++nlineas; /* fin de linea es CR LF*/ [^ \t\n]+ ++npalabras, ncaracteres += yyleng; . ++ncaracteres; %% main() { yylex(); printf("%d %d %d\n",ncaracteres,npalabras,nlineas); exit(0); }
37
Solucin ejercicio 4
%% [^ \t\n]* { char auxiliar; int cont; for(cont = 1; cont <= (yyleng / 2); cont++) { auxiliar = yytext[cont - 1]; yytext[cont - 1] = yytext[yyleng - cont]; yytext[yyleng - cont] = auxiliar; }; ECHO; } %% int main() { yylex(); }
38
Solucin ejercicio 5
%% [0-9]+ ECHO; [^ \t\n]* { char auxiliar; int cont; for(cont = 1; cont <= (yyleng / 2); cont++) { auxiliar = yytext[cont - 1]; yytext[cont - 1] = yytext[yyleng - cont]; yytext[yyleng - cont] = auxiliar; }; ECHO; } %% int main() { Cul sera el yylex(); 1. C/ Barbero, }
39
Solucin ejercicio 6
%% [^\n]* { char auxiliar; int cont; for(cont = 1; cont <= (yyleng / 2); cont++) { auxiliar = yytext[cont - 1]; yytext[cont - 1] = yytext[yyleng - cont]; yytext[yyleng - cont] = auxiliar; }; ECHO; } %% int main() { yylex(); }
40
41
Solucin Ejercicio 7
%{ char auxiliar; int cont, agrupador; #define REVES(paso) cont = yyleng - paso; do { for(agrupador = 0; agrupador < paso; agrupador ++){ if (yytext[cont + agrupador] != '\0') { printf("%c", yytext[cont + agrupador]); yytext[cont + agrupador] = '\0'; } } if (cont > 0) { cont -= paso; if (cont < 0) cont = 0; } else cont = -1; } while (cont >= 0); %} %% [^ \t\n]{1,4} { REVES(1); } [^ \t\n]{5,6} { REVES(2); } [^ \t\n]{7,9} { REVES(3); } [^ \t\n]* { REVES(4); } %%
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
42
Ejercicio 8
La Secretara de la E.T.S.I. de Informtica recibe de los Departamentos las notas de los alumnos en un fichero formato texto, en el que cada lnea posee tres campos separados por espacios: D.N.I. del alumno, Convocatoria del examen (Diciembre, Febrero o Junio), y la Nota. Hacer un programa LEX que efecte la lectura de dicho fichero, emitiendo al final la media de las notas recuperadas. Asimismo informar de los errores de formato que se pueda encontrar: lneas en las que falten campos, valores incorrectos, etc NOTAS: Para convertir un array de caracteres a un nmero usar sscanf(yytext,%d,¬a); donde nota es una variable de tipo entero.
43
int yyinput(void);
void yyunput(int); Es una interfaz para la macro unput(). void yyoutput(int); Es una interfaz para la macro output(). Esta funcion sirve para manejar las condiciones de fin de archivo, cada vez que el lexer llega a un fin de archivo, llama a esta funcion para saber que hacer, si regresa 0, entonces sigue leyendo de la entrada, si es 1 el lexer regresa un token nulo para indicar que se llego al fin de archivo. Esta es la funcin principal de un lexer, para aadir cdigo a esta funcin, es necesario, incluirlo en la seccin de reglas encerrado entre %{ y %}.
int yywrap(void);
int yylex(void);
44
Ejemplo 8
Si quisiramos cambiar la entrada estndar para que se lea desde un archivo:
main(int argc, char *argv[]){ If (argc==2) { //por default yyin apunta a stdin, ahora lo cambiamos. yyin = fopen(argv[1],r); } Yylex(); }
45
Ejemplo 9
Ahora entrada y salida estndar:
int main(int argc, char *argv[]){ if (argc==2){ //por default yyin apunta a stdin, // se cambia al archivo 1 pasado por argumento. yyin = fopen(argv[1],"r"); } if (argc==3) yyin = fopen(argv[1],"r"); //por default yyout apunta a stout, // se cambia al archivo 2 pasado por argumento. yyout = fopen(argv[2],"w"); } yylex(); }
46
Bibliografa
Tutorial de Lex y Yacc
http://www.medinaweb.com/programas/documents/tutoriales/lex_yacc/core/l exyak.html
Sergio Glvez Rojas. Libro Electrnico: Java a tope: Traductores y compiladores con Lex/Yacc, JFlex/Cup y JavaCC, Universidad de Mlaga. La pgina de Lex y Yacc
http://dinosaur.compilertools.net/
47