Sunteți pe pagina 1din 20

FLEX: Un generador de analizadores léxicos

• Como hemos visto, el paso de una expresión regular a un AF se


puede hacer de manera automatizada
• Existen varias herramientas que relizan dicho trabajo
• Generadores de analizadores léxicos
– AT&T Lex (más común en UNIX)
– MKS Lex (MS-Dos)
– Flex
– Abraxas Lex
– Posix Lex
– ScanGen
– JLex
– ...

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 1


FLEX: Un generador de analizadores léxicos

• ¿Qué hace LEX?


especifica un analizador
léxico

especificación
FLEX

FLEX
FLEX
lex.yy.c

int yylex(): función que realiza el análisis


léxico

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 2


FLEX: Un generador de analizadores léxicos

• FLEX sigue el esquema: patrón1 { acción1 }


patrón2 { acción2 }
.......
donde: patrónk { acciónk }
– patrón: expresión regular
– acción: fuente C con las acciones a realizar cuando el patrón concuerde
con un lexema
• Funcionamiento:
– FLEX recorre entrada estándar hasta que encuentra una concordancia
» un lexema correspondiente al lenguaje de algunas de las e.r.
representadas por los patrones
– entonces, ejecuta el código asociado (acción)
– permite acceder a la información asociada al lexema (string, longitud del
mismo, nº de línea en el fuente,...)

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 3


FLEX: Un generador de analizadores léxicos

• Ejemplo: implementar en LEX, un analizador léxico para

menor →
menor → <<
mayor →
mayor → >>
menorIgual →
menorIgual → <=
<=
mayorIgual →
mayorIgual → >=
>=
igual →
igual → ==
distinto →
distinto → <>
<>
letra →
letra → a|b|...|z|A|B|....|Z
a|b|...|z|A|B|....|Z
digito →
digito → 0|1|...|9
0|1|...|9
identificador →
identificador → letra
letra (letra
(letra |digito)*
|digito)*
constEntera →
constEntera → digito
digito digito
digito **

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 4


FLEX: Un generador de analizadores léxicos

• Comportamiento deseado:
v0<>27 segundos= 1000

analizador
analizador
léxico
léxico

(IDENTIFICADOR,v0)
(DISTINTO,)
(CONSTENTERA,27)
(IDENTIFICADOR,segundos)
(IGUAL,)
(CONSTENTERA ,1000)

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 5


FLEX: Un generador de analizadores léxicos

• Estructura de sección
sección de
de definiciones
definiciones
un programa FLEX %%
%%
sección
sección de
de reglas
reglas
%%
%%
sección
sección de
de rutinas
rutinas del
del usuario
usuario

• Sección de definiciones:
– bloques literales
» se copian “tal cual” al fuente lex.yy.c
» entre ‘%{‘ y ‘%}’
– definiciones regulares (“bautismo”)
– declaraciones propias para el manejo de tablas de LEX
– condiciones iniciales
» cambiar el funcionamiento del reconocedor

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 6


FLEX: Un generador de analizadores léxicos

%{
%{ /*
/* fichero:
fichero: expresiones.l
expresiones.l */
*/
#include
#include ....
....
enum
enum {MENOR=255,MENORIGUAL,MAYOR,
{MENOR=255,MENORIGUAL,MAYOR,
MAYORIGUAL,IGUAL,DISTINTO,
MAYORIGUAL,IGUAL,DISTINTO,
IDENTIFICADOR,CONSTENTERA};
IDENTIFICADOR,CONSTENTERA};
int
int yylval;
yylval;
/*
/* para
para atributo
atributo cte.
cte. entera*/
entera*/
typedef int token;
typedef int token;
%}
%}
%%
%%
sección
sección dede reglas
reglas
%%
%%
sección
sección dede rutinas
rutinas de
de usuario
usuario

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 7


FLEX: Un generador de analizadores léxicos

• Sección de reglas
– Formato: patrón {acciones}

– dos tipos de líneas:


» empiezan por blanco, ‘%{‘ ó ’%}’ fuente C
» empiezan por otra cosa: línea patrón-código
– las líneas de fuente C se copian directamente en el fuente lex.yy.c
– al encontrar concordancia, ejecutará código asociado
– si no encuentra concordancia, ejecuta ECHO (copia el lexema en salida
estándar)

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 8


FLEX: Un generador de analizadores léxicos

%{
%{
sección
sección de
de definiciones
definiciones
%}
%}
%%
%%
(\t|\n|"
(\t|\n|" ")+
")+ {/*
{/* no
no hace
hace nada
nada */};
*/};
[0-9]([0-9])*
[0-9]([0-9])* {sscanf(yytext,"%d",&yylval);
{sscanf(yytext,"%d",&yylval);
return(CONSTENTERA);}
return(CONSTENTERA);}
"<"
"<" {return(MENOR);}
{return(MENOR);}
....
....
....
....
"<>"
"<>" {return(DISTINTO);}
{return(DISTINTO);}
[a-zA-Z]([a-zA-Z]|[0-9])*
[a-zA-Z]([a-zA-Z]|[0-9])* {return(IDENTIFICADOR);}
{return(IDENTIFICADOR);}
.. {ECHO;}
{ECHO;}
%%
%%
sección
sección de
de rutinas
rutinas de
de usuario
usuario

patrón
acción
Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 9
FLEX: Un generador de analizadores léxicos

• Sección de rutinas de usuario


– su contenido se copia literalmente en el fuente lex.yy.c
– contiene funciones C escritas por el usuario y necesarias para el
analizador
» manejo de tabla de símbolos
» generación de salidas (cuando no es necesario generación de código)

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 10


FLEX: Un generador de analizadores léxicos

%{
sección de definiciones
%}
%% /*--------------------------------------
Cuando EOF, yylex() dev. 0
sección de reglas ---------------------------------------*/
%% int main()
/*--------------------------------------
Sólo para comprobación
{ token elToken;
---------------------------------------
*/ elToken=yylex();
void escribeInfo(token elToken) while(elToken){
{ switch(elToken){ escribeInfo(elToken);
case IDENTIFICADOR: elToken=yylex();
fprintf(stdout, }
"ident.\t%s",yytext); }
break;
..........
}
}

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 11


FLEX: Un generador de analizadores léxicos

• Ejemplo de uso de LEX: sufijo ‘.l’


para fuente FLEX
expresiones.l

invocación a FLEX
flex expresiones.l
fuente con el
analizador
lex.yy.c
-lfl: biblioteca
necesaria
gcc -o expresiones
lex.yy.c -lfl
analizador

expresiones
Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 12
FLEX: Un generador de analizadores léxicos

#=====================================================
# Fichero: Makefile
# Tema: genera un analizador léxico para
# introducir Flex/Lex
# Fecha: Septiembre-03
# Uso: make
#=====================================================
LEX=flex
CC=gcc

expresiones: lex.yy.o
$(CC) -o expresiones lex.yy.o -lfl
#-L/opt/flex/lib -lfl para Merlin
lex.yy.o: lex.yy.c
$(CC) -c lex.yy.c

lex.yy.c: expresiones.l
$(LEX) expresiones.l

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 13


FLEX: Un generador de analizadores léxicos

• Ejemplo de invocación:
– el fichero ‘entrada’ es v0<>27
segundos= 1000

– invocación: expresiones < entrada

– genera la siguiente salida identificador v0


distinto <>
numero 27
identificador segundos
igual =
numero 1000

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 14


FLEX: Un generador de analizadores léxicos

• También se pueden dar nombres a expresiones regulares


%{
%{ /*
/* fichero:
fichero: expresiones.l
expresiones.l */
*/
......
......
int yylval;
int yylval; /*
/* hab.
hab. los
los define
define Yacc
Yacc */
*/
typedef int token;
typedef int token;
%}
%}
separadores
separadores [\n\t
[\n\t ]+]+
.....
.....
letra
letra [a-zA-Z]
[a-zA-Z]
digito
digito [0-9]
[0-9]
identificador {letra}({letra}|{digito})*
identificador {letra}({letra}|{digito})*
constEntera
constEntera {digito}({digito})*
{digito}({digito})*
%%
%%
sección
sección de de reglas
reglas
%%
%%
sección
sección de
de rutinas
rutinas dede usuario
usuario

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 15


FLEX: Un generador de analizadores léxicos
%{
%{
sección
sección de
de definiciones
definiciones
%}
%}
%%
%%
{separadores}
{separadores} {/*
{/* no
no hace
hace nada
nada */};
*/};
{constEntera} {sscanf(yytext,"%d",&yylval);
{constEntera} {sscanf(yytext,"%d",&yylval);
return(CONSTENTERA);}
return(CONSTENTERA);}
....
....
{identificador}
{identificador} {return(IDENTIFICADOR);}
{return(IDENTIFICADOR);}
.. {ECHO;}
{ECHO;}
%%
%%
sección
sección de
de rutinas
rutinas de
de usuario
usuario
Nota: el nombre de la ER en la parte
de patrones debe ponerse entre
‘{‘ y ‘}’ para distinguirlo del
patrón literal

{separadores}<>separadores

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 16


FLEX: Un generador de analizadores léxicos

• Extensiones .. cualquier
cualquier carácter
carácter excepto
excepto “\n”
“\n”
de FLEX a r*
r*
r+
00 óó más concat. de
más concat. de r
11 óó más
r
e.r. r+ más concat.
concat. de
de rr
r?
r? 00 óó 11 veces
veces rr
[c
[c11...c
...cnn]] conj.caracteres
conj.caracteres {c {c11...c
...cnn}}
a-b
a-b caracteres
caracteres {a,succ(a),...}
{a,succ(a),...}
^r
^r rr debe
debe concordar al
concordar al principio
principio
de la línea
de la línea
[^c
[^c11...c
...cnn]] cualquier
cualquier car.∉{c
car.∉{c11...c
...cnn}}
r$
r$ rr debe
debe concordar
concordar al
al terminar
terminar
la línea
la línea
r{m,n}
r{m,n} entre
entre mm yy nn concatenaciones
concatenaciones
de r
de r
\\ para
para concordancia
concordancia exacta
exacta de de
caracteres
caracteres especiales: \\ \.
especiales: \\ \. \?
\?
r1|r2
r1|r2 lo habitual
lo habitual
“c
“c11...c
...cnn““ literalmente
literalmente cc11...c
...cnn
r1/r2
r1/r2 reconoce
reconoce r1 sólo si
r1 sólo si vava
seguida de
seguida de r2 r2 (¿e.r.?)
(¿e.r.?)
Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 17
FLEX: Un generador de analizadores léxicos

• ¿Qué pasa cuando .....


hay ambigüedad? letra [a-zA-Z]
digito [0-9]
• FLEX aplica dos identificador {letra}({letra}|{digito})*
reglas: %%
“if” {return(IF);}
{identificador} {return(IDENT);}
Regla 1 %%

Aplica el patrón que concuerde con el string más


largo
Regla 2
Si dos patrones representa el mismo string, aplica
el que aparece antes en las declaraciones de LEX

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 18


Un ejemplo: contar caracteres, líneas y palabras

#include <stdio.h>
int nCar=0, nPal=0, nLin=0;
Una versión
%}
“a las bravas”
palabra [^ \t\n]+
finLin \n
%%
{palabra} {nCar+=yyleng;nPal++;}
{finLin} {nCar++;nLin++;}
. {nCar++;}
%%
int main(){
yylex();
fprintf(stdout,
"car:%d pal:%d lin:%d\n",
nCar, nPal, nLin
);
}

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 19


Un ejemplo: contar caracteres, líneas y palabras
un poco más
estructurada
#include <stdio.h> int elToken; y elegante
enum {PALABRA=128,FINLINEA, elToken=yylex();
OTROSEP};
int nCar=0, nPal=0, nLin=0; while(elToken){
%} switch(elToken){
palabra [^ \t\n]+ case PALABRA: nPal++;nCar+=yyleng;
finLin \n break;
%% case FINLINEA:nCar++;nLin++;
{palabra} {return PALABRA;} break;
{finLin} {return FINLINEA;} case OTROSEP: nCar++;
. {return OTROSEP;} }
%% elToken=yylex();
int main(){ }
fprintf(stdout,
} "car:%d pal:%d lin:%d\n",
nCar, nPal, nLin
);

Compiladores I. C.P.S. Universidad de Zaragoza -J.Ezpeleta- 20

S-ar putea să vă placă și