Académique Documents
Professionnel Documents
Culture Documents
Software de Sistemas
Mónica Pinto Alarcón
Curso 2005/2006
Introducción
2/38
1
Introducción
Un analizador léxico:
Ejemplo 1
Tabla de Símbolos
TOKEN ATRIBUTO SIMBOLO INFORMACIÓN
IDENT posición Ej. tipo de la variable
IDENT principal ...
IDENT velocidad ...
ENTERO 60
4/38
2
Funciones del Analizador Lexicográfico
Funciones Básicas
Leer carácter a carácter del programa fuente.
Entregarle los tokens identificados al analizador sintáctico
Producir parte del listado con los errores de compilación
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 posición en la
tabla de símbolos.
Relacionar mensajes de error con el número de línea en el
que aparecen.
5/38
ASIG := := :=
MAS + + +
ENTERO 47, 1234567, (0+...+9)(0+...+9)* [0-9]+
0
PR_FOR For, for, FOR (F+f)(O+o)(R+r) [Ff][Oo][Rr]
6/38
3
Lexemas, expresiones regulares y tokens
Lexemas:
Son caracteres o conjuntos de caracteres (palabras) que
pertenecen al léxico del lenguaje.
Expresiones Regulares (Patrones):
Definen las reglas que permiten identificar los componentes
léxicos o tokens.
Tokens:
Son los componentes léxicos generados por el analizador
lexicográfico
Atributos:
Son información adicional para cada componente léxico que
serán utilizadas en el análisis semántico y/o en la fase de
síntesis (ej. Lexema, Tipo, Valor, Línea).
Depende del token
7/38
Ejemplo 2
Expresiones Regulares
a*(b | c)+ Æ L1 = {w : w=a*(b | c)+}
bccbcbccbc
abbbccc
abbcbcccbbc
(0-9)*.(0-9)+ Æ L2 = {w: w=(0-9)*.(0-9)+}
0.236425
3567.45627 a* Æ 0 o más “a”
.753473 (b | c) Æ “b” o “c”
5.0 c+ Æ 1 o más “c”
0-9 Æ 0 ó 1 2 ó …ó 9
8/38
4
Ejemplo 3
Expresión Regular Token Atributos
end end -
loopif loopif -
read read -
start start -
var var -
write write -
[0-9]+ entero valor
[a-zA-Z](_?([a-zA-Z0-9]))* id Puntero tabla símbolos
, coma -
; pyc -
( pari -
) pard -
[+-] opsum Constante identificando + o –
[*/] opmul Constante identificando * o /
“<“|”>”|”<=“|”=>”|”<>”|”=“ oprel Constante identificando op.
:= asig -
[ \n] - -
. - - 9/38
10/38
5
LEX
Uso básico:
Implementación de la fase de Análisis
Lexicográfico de un compilador
Uso combinado con el Analizador sintático YACC
Otros usos de Lex:
Transformaciones sencillas de ficheros fuente
Ej: Dado un texto completamente en mayúsculas
convertirlo en un texto en formato “frase”: mayúscula
sólo la primera letra de una palabra tras un punto.
11/38
LEX
12/38
6
Ejemplo 4
%%
[ \t]+$ ;
13/38
14/38
7
Ejemplo 6
Órdenes:
%%
integer printf(“Localizada palabra reservada INT”);
float printf(“Localizada palabra reservada FLOAT”);
15/38
Ejemplo 7
16/38
8
Expresiones Regulares en Lex
17/38
Clases de Caracteres
[abc]
Cualquier carácter que sea una “a” o una “b” o una “c”
[a-z0-9<>_]
Cualquier carácter desde la “a” a la “z” o un dígito del “0” al
“9”, o “<“ o “>” o “_”
[-+0-9]
Cualquier dígito o los signos “-” y “+”
Como “-” es un operador para incluirlo como carácter debe ir
al principio de la clase de caracteres
[^abc]
Todos los caracteres excepto “a”, “b” y “c”
18/38
9
Expresiones Regulares en Lex
19/38
20/38
10
Expresiones Regulares en Lex
21/38
Acciones en LEX
22/38
11
Acciones en LEX
23/38
24/38
12
Sección de Definiciones en LEX
25/38
Ejemplo 8
Sección de definiciones
D [0-9]
E [DEde][-+]?{D}+
Sección de órdenes
%%
{D}+ printf(“integer”);
{D}+”.”{D}*({E})?|
{D}*”.”{D}+({E})?|
{D}+{E} printf(“real”);
26/38
13
LEX y YACC
27/38
Ejercicio 1
28/38
14
Solución Ejercicio 1
%%
int main()
{
yylex();
} 29/38
Ejercicio 2
30/38
15
Solución Ejercicio 2
%%
int main()
{
yylex(); 31/38
}
Ejercicios 3, 4, 5 y 6
32/38
16
Solución Ejercicio 3
%{
#include <stdlib.h>
static unsigned ncaracteres = 0; /* número de caracteres*/
static unsigned npalabras = 0; /* número de palabras*/
static unsigned nlineas = 0; /* número 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);
}
33/38
Ejercicios 3, 4, 5 y 6
34/38
17
Solución 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();
}
35/38
Ejercicios 3, 4, 5 y 6
36/38
18
Solución 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;
}
%%
¿Cuál sería el resultado de cifrar
int main()
{
yylex(); 1. C/ Barbero, nº 28
} 2. C/ Barbero, nº28?
37/38
Ejercicios 3, 4, 5 y 6
38/38
19
Solución 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();
}
39/38
Ejercicio 7
40/38
20
Solución 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); } 41/38
%%
Ejercicio 8
42/38
21