Sunteți pe pagina 1din 20

Construccin de un analizador lxico para ASPLE con Lex/Flex

ndice (i) Marina de la Cruz


AlfonsoOrtega

Funciones del analizador lxico/morfolgico


Construccin de un analizador lxico/morfolgico
Funcionamiento bsico de Lex/Flex
El fichero de especificacin Lex/Flex
Estructura del fichero
La seccin de definiciones
La seccin de reglas
La seccin de funciones de usuario
Primer ejemplo
El fichero de especificacin
Creacin del ejecutable
Realizacin de pruebas
Segundo ejemplo
Diseo del fichero de especificacin
El fichero de especificacin
Creacin del ejecutable y realizacin de pruebas
Modificacin del diseo
1
Prcticas de compiladores 2004-2005

Construccin de un analizador lxico para ASPLE con Lex/Flex


ndice (ii) Marina de la Cruz
AlfonsoOrtega

Los patrones de Lex/Flex


Descripcin
Metacaracteres
Cmo se identifican los patrones en la entrada
Tercer ejemplo
Enunciado
Realizacin de pruebas
Los tokens del lenguaje ASPLE
Identificacin
Patrones o expresiones regulares
Fichero de especificacin Lex/Flex para el lenguaje ASPLE
Construccin
El orden de las reglas
Gestin de los espacios en blanco
Control de la posicin de los tokens en el fichero de entrada
Gestin de los comentarios
Gestin de errores
Ficheros de entrada/salida de Lex/Flex

2
Prcticas de compiladores 2004-2005
Funciones del analizador lxico/morfolgico

El analizador lxico/morfolgico de un compilador es el responsable de identificar


en el fichero del programa fuente los tokens del lenguaje particular para el que ha
sido construido el analizador.

Fichero del
programa fuente Analizador lxico tokens

Adems de identificar los tokens tambin se encarga de otras tareas como:


eliminar espacios en blanco (blancos, tabuladores y saltos de lnea)
eliminar comentarios
detectar errores morfolgicos (smbolo no permitido, identificador demasiado largo, etc)

3
Prcticas de compiladores 2004-2005

Construccin de un analizador lxico/morfolgico

Un analizador morfolgico se puede desarrollar con distintos mtodos:


con un autmata finito
con un programa a medida
utilizando una herramienta especfica como Lex/Flex

Independientemente del mtodo seleccionado, para construir el analizador


morfolgico, hay que definir los requisitos que debe cumplir el analizador:
los tokens que tiene que reconocer:
identificadores
palabras reservadas
constantes (numricas, booleanas, literales, etc)
smbolos simples (+, -, *. /, etc)
smbolos mltiples (+=, >=, etc)
el formato de los comentarios
los errores morfolgicos que debe detectar

4
Prcticas de compiladores 2004-2005
Funcionamiento bsico de Lex/Flex

Lex/Flex es una herramienta para construir analizadores lxicos.


Lex/Flex recibe como entrada un conjunto de descripciones de tokens, y genera la
funcin C yylex() que es un analizador lxico que reconoce dichos tokens.
Los tokens se describen mediante patrones que son extensiones de las
expresiones regulares.
Al conjunto de las descripciones de tokens se le llama especificacin lex/flex.
Especificacin
Lex/Flex

Lex/Flex

lex.yy.c

Fichero del
programa yylex() tokens
fuente

5
Prcticas de compiladores 2004-2005

El fichero de especificacin Lex/Flex (I)


Estructura del fichero
La estructura del fichero de especificacin Lex/Flex se compone de tres
secciones separadas por lneas que contienen el separador %%.

seccin de definiciones

%{
/* delimitadores de cdigo C */
%}

%%

seccin de reglas

%%

seccin de funciones de usuario

6
Prcticas de compiladores 2004-2005
El fichero de especificacin Lex/Flex (II)
La seccin de definiciones (i)
La seccin de definiciones contiene la siguiente informacin
Cdigo C encerrado entre lneas con los caracteres %{ y %} que se copia
literalmente en el fichero de salida lex.yy.c antes de la definicin de la funcin
yylex(). Habitualmente esta seccin contiene declaraciones de variables y
funciones que se utilizan posteriormente en la seccin de reglas as como directivas
#include.
Definiciones propias de Lex/Flex, que permiten asignar un nombre a una expresin
regular o a una parte, y posteriormente utilizar ese nombre en la seccin de reglas.
Estas definiciones se vern con ms detalle cuando se estudien los patrones de
Lex/Flex.
Opciones de Lex/Flex similares a las opciones de la lnea de comandos.
Definicin de condiciones de inicio. Estas definiciones se vern con ms detalle
cuando se estudien los patrones de Lex/Flex.
Cualquier lnea que empiece con un espacio en blanco se copia literalmente en el
fichero de salida lex.yy.c. Habitualmente se utiliza para incluir comentarios
encerrados entre /* y */.

7
Prcticas de compiladores 2004-2005

El fichero de especificacin Lex/Flex (III)


La seccin de definiciones (ii)
Seccin de definiciones del primer ejemplo de Lex/Flex
El primer ejemplo de utilizacin de Lex/flex que se va a construir es un analizador
lxico que reconoce en la entrada las palabras clave begin y end, y que cada vez
que encuentra una de ellas muestra en la salida estndar un mensaje de aviso de
token reconocido.
El fichero de especificacin Lex/Flex se llamar ej1.l, y en la figura se muestra
una primera aproximacin del mismo en la que nicamente se ha completado la
seccin de definiciones. A medida que se construya el ejemplo se completarn las
dems secciones.
La directiva #include <stdio.h> se necesita porque en la seccin de reglas se
utiliza la funcin printf para mostrar en la salida estndar los mensajes de aviso
de token reconocido.
El significado de la opcin noyywrap se explica en el siguiente apartado.

ej1.l %{
#include <stdio.h> /* para utilizar printf en la
seccin de reglas */
%}

%option noyywrap

%%
8
Prcticas de compiladores 2004-2005
El fichero de especificacin Lex/Flex (IV)
La seccin de definiciones (iii)
Significado de la opcin noyywrap:
Existe la posibilidad de que la funcin yylex() analice morfolgicamente varios
ficheros, encadenando uno detrs de otro con el siguiente mecanismo.
Cuando yylex() encuentra un fin de fichero, llama a la funcin yywrap(). Si la
funcin devuelve 0, el anlisis contina con otro fichero, y si devuelve 1, el anlisis
termina.
Quin proporciona la funcin yywrap()?
En Linux, la librera de lex proporciona una versin por defecto de yywrap()
que devuelve 1. Hay que enlazar con esa librera.
En Windows la tiene que proporcionar el usuario incorporndola en la ltima
seccin del fichero de especificacin. En Linux tambin la puede proporcionar
el usuario.
La opcin noyywrap provoca que no se invoque a la funcin yywrap() cuando se
encuentre un fin de fichero, y se asuma que no hay ms ficheros que analizar.
Esta solucin es ms cmoda que tener que escribir la funcin o bien enlazar con
alguna librera.

9
Prcticas de compiladores 2004-2005

El fichero de especificacin Lex/Flex (V)


La seccin de reglas (i)
La seccin de reglas contiene:
Los patrones que describen los tokens y cdigo C.
Cada patrn se sita en una lnea, seguido de uno o ms espacios en blanco y a
continuacin el cdigo C que se ejecuta cuando se encuentra dicho patrn en la
entrada que se est analizando. El cdigo C se cierra entre llaves { }.
Si una lnea empieza por un espacio en blanco se considera cdigo C y se copia
literamente en el fichero de salida. Tambin se asumeque es cdigo C todo lo que
se escriba entre %{ y %}, y se copia literalmente en el fichero de salida.
Cmo se comporta la rutina de anlisis yylex()?
Busca en la entrada los patrones que se definen en la seccin de reglas, es decir,
los tokens. Cada vez que se encuentra un token, se ejecuta el cdigo C asociado
con el patrn. Si no se identifica ningn token, la regla por defecto se ejecuta: el
siguiente caracter en la entrada se considera reconocido y se copia en la salida.
El cdigo C asociado a cada patrn puede tener una sentencia return, que
devuelve un valor al llamador de la funcin yylex()cuando se identifique el patrn
en la entrada. La siguiente llamada a yylex() comienza a leer la entrada en el
punto donde se qued la ltima vez. Cuando se encuentra el fin de la entrada
yylex() devuelve 0 y termina.
Si ninguna regla tiene una sentencia return, yylex() analiza la entrada hasta
que encuentra el fin de la misma.
10
Prcticas de compiladores 2004-2005
El fichero de especificacin Lex/Flex (VI)
La seccin de reglas (ii)
Seccin de reglas del primer ejemplo:
Los patrones de Lex/Flex para definir los tokens se estudiarn ms adelante, y ya se
ver que el patrn para representar una palabra clave es la misma palabra clave.
La seccin de reglas del primer ejemplo contiene:
un patrn para la palabra clave begin, que es la misma palabra, y el cdigo C
que se va a ejecutar cuando se identifique en la entrada. El cdigo muestra en
la salida estndar el aviso reconocido-begin-.
Un patrn para la palabra clave end, que es la misma palabra, y su cdigo C
asociado que muestra en la salida estndar el aviso reconocido-end-.

ej1.l %{
#include <stdio.h> /* para utilizar printf en la
seccin de reglas */
%}
%option noyywrap

%%

begin { printf(reconocido-begin-\n); }
end { printf(reconocido-end-\n); }

%%
11
Prcticas de compiladores 2004-2005

El fichero de especificacin Lex/Flex (VII)


La seccin de funciones de usuario
La seccin de funciones de usuario se copia literalmente en el fichero de salida.
Esta seccin habitualmente contiene las funciones escritas por el usuario para
ser utilizadas en la seccin de reglas, es decir, funciones de soporte.
En esta seccin tambin se incluyen las funciones de Lex/Flex que el usuario
puede redefinir, por ejemplo la funcin yywrap() se situara en esta seccin.
La funcin yylex() generada por Lex/Flex, tiene que ser invocada desde
algn punto, habitualmente desde el analizador sintctico. Pero para realizar
pruebas de la funcin yylex() se incorpora una funcin main en la seccin de
funciones de usuario dentro del fichero de especificacin Lex/Flex. Una versin
muy simple sera:

int main()
{
return yylex();
}

Esta llamada nica a yylex() permite realizar el anlisis lxico hasta encontrar
el fin de la entrada siempre que en ningn fragmento de cdigo C asociado a los
patrones de los tokens aparezca una sentencia return que haga terminar a
yylex(). En ese caso el main sera distinto como se mostrar mas adelante.
12
Prcticas de compiladores 2004-2005
Primer ejemplo (I)
El fichero de especificacin ej1.l
Se completa el fichero ej1.l incluyendo una funcin main en la seccin de
funciones de usuario.

ej1.l %{
#include <stdio.h> /* para utilizar printf en la
seccin de reglas */
%}
%option noyywrap

%%

begin { printf(reconocido-begin-\n); }
end { printf(reconocido-end-\n); }

%%

int main()
{
return yylex();
}

13
Prcticas de compiladores 2004-2005

Primer ejemplo (II)


Creacin del ejecutable
A partir del fichero de especificacin Lex/Flex ej1.l se genera el ejecutable de
la siguiente manera:
Compilar la especificacin Lex/Flex

flex ej1.l se crea el fichero lex.yy.c

Generar el ejecutable:
Linux: gcc -Wall -o ej1 lex.yy.c se crea el fichero ej1
Windows: cl /W4 /Feej1.exe lex.yy.c se crea el fichero ej1.exe

14
Prcticas de compiladores 2004-2005
Primer ejemplo (III)
Realizacin de pruebas
Para probar el funcionamiento del analizador lxico implementado en el primer
ejemplo, se arranca el ejecutable y se realizan las siguientes pruebas:

cadena cualquiera No se identifica ningn token.


cadena cualquiera
Se copia la entrada en la salida.
begin Se identifica el token begin.
reconocido-begin-
Se muestra un mensaje de aviso.
end Se identifica el token end.
reconocido-end-
Se muestra un mensaje de aviso.
beginend Se identifican los tokens begin y end.
reconocido-begin- Observar que ambos tokens se
reconocido-end- reconocen aunque no estn separados.
Se muestran los mensajes de aviso
correspondientes.
^Z/^D Fin de la entrada
Windows / Linux
Texto azul: entrada del usuario
Texto rojo: respuesta del analizador

15
Prcticas de compiladores 2004-2005

Segundo ejemplo (I)


Diseo del fichero de especificacin (i)

En el primer ejemplo, la funcin main invoca a la funcin yylex() una sola vez, y
como en ninguna de las reglas aparece una sentencia return, la funcin
yylex() se ejecuta hasta encontrar el fin de la entrada.
En el segundo ejemplo, se quiere modificar la especificacin Lex/Flex para que la
funcin yylex() devuelva un valor diferente para cada token identificado, y la
funcin main sea la responsable de mostrar por la salida estndar el aviso
correspondiente del token identificado.
Los cambios que hay que hacer son los siguientes:
definir constantes diferentes para los tokens. En la seccin de definiciones se aaden
las siguientes sentencias:

#define TOK_BEGIN 1
#define TOK_END 2
modificar la seccin de reglas para que el cdigo C asociado a cada token en lugar de
mostrar en la salida estndar un aviso, devuelva la constante definida para el token.

begin { return TOK_BEGIN; }


end { return TOK_END; }

16
Prcticas de compiladores 2004-2005
Segundo ejemplo (II)
Diseo del fichero de especificacin (ii)
Modificar la funcin main para que llame a la funcin yylex() y muestre un mensaje
de aviso diferente para cada token en funcin del valor devuelto por yylex(). La
funcin main llama repetidas veces a la funcin yylex() hasta que se termina la
entrada, es decir, hasta que la funcin yylex() devuelve 0.
int main()
{
int token;
while (1)
{
token = yylex();
if (token == TOK_BEGIN)
printf(reconocido-begin-\n);
if (token == TOK_END)
printf(reconocido-end-\n);
if (token == 0)
break;
}
return 0;
}
17
Prcticas de compiladores 2004-2005

Segundo ejemplo (III)


El fichero de especificacin ej2.l
ej2.l %{
#include <stdio.h>
#define TOK_BEGIN 1
#define TOK_END 2
%}
%option noyywrap
%%
begin { return TOK_BEGIN; }
end { return TOK_END; }
%%
int main()
{
int token;
while (1)
{
token = yylex();
if (token == TOK_BEGIN) printf(reconocido-begin-\n);
if (token == TOK_END) printf(reconocido-end-\n);
if (token == 0) break;
}
return 0;
}
18
Prcticas de compiladores 2004-2005
Segundo ejemplo (IV)
Creacin del ejecutable y realizacin de pruebas
A partir del fichero de especificacin Lex/Flex ej2.l se genera el ejecutable:
Compilar la especificacin Lex/Flex

flex ej2.l se crea el fichero lex.yy.c

Generar el ejecutable:
Linux: gcc -Wall -o ej2 lex.yy.c se crea el fichero ej2
Windows: cl /W4 /Feej2.exe lex.yy.c se crea el fichero ej2.exe

Si se realizan las mismas pruebas que se hicieron con ej1.exe se obtendrn los
mismos resultados ya que no se ha modificado la funcionalidad del analizador
lxico sino su diseo.

19
Prcticas de compiladores 2004-2005

Segundo ejemplo (V)


Modificacin del diseo
La definicin de los tokens se traspasa a un fichero de cabecera tokens_ej2.h, y
se incluye dicho fichero en el fichero de especificacin ej2.l.
Tokens_ej2.h #ifndef _TOKENS_EJ2_H
#define _TOKENS_EJ2_H

#define TOK_BEGIN 1
#define TOK_END 2

#endif

ej2.l %{
#include <stdio.h>
#include tokens_ej2.h
%}
%option noyywrap
%%
begin { return TOK_BEGIN; }
end { return TOK_END; }
%%
int main()
{
int token;
...................
20
Prcticas de compiladores 2004-2005
Los patrones de Lex/Flex (I)
Descripcin
Los patrones de Lex/Flex son:
el mecanismo para representar los tokens.
una extensin de las expresiones regulares.
Los patrones estn formados por:
caracteres normales que se representan a s mismos
metacaracteres que tienen un significado especial
Para utilizar un metacaracter como caracter normal hay que ponerlo entre
comillas. Por ejemplo, el asterisco es un metacaracter, y si se quiere reconocer
el token asterisco, hay que definirlo como *.
En los siguientes apartados se describen algunos de los metacaracteres de
Lex/Flex, en concreto, aquellos que son necesarios para especificar los tokens
del lenguaje ASPLE.
Un mismo token se puede expresar con distintos patrones.

21
Prcticas de compiladores 2004-2005

Los patrones de Lex/Flex (II)


Metacaracteres (i)

. Representa cualquier caracter exceptuando el salto de lnea "\n".

[] Representa cualquiera de los caracteres que aparecen dentro de los corchetes.


Para indicar un rango de caracteres se utiliza el smbolo menos "-".

[xyz] representa una "x", una "y" o una "z"


[abj-oZ] representa una "a", una "b" cualquier letra de la "j" a la "o", o una "Z"
[ \t] representa el espacio y el tabulador
[0-9] representa los dgitos del 0 al 9
[a-z] representa las letras minsculas
[A-Z] representa las letras maysculas
[a-zA-Z] representa las letras minsculas y las maysculas
[0-9a-zA-Z] representa los dgitos del 0 al 9, las letras minsculas y las
maysculas

22
Prcticas de compiladores 2004-2005
Los patrones de Lex/Flex (III)
Metacaracteres (ii)

* Indica 0 ms ocurrencias de la expresin que le precede.

ab* representa todas las palabras que empiezan por una "a" seguida de 0 o ms
"b", por ejemplo "a", "ab", "abb", "abbb".
[a-zA-Z][a-zA-Z0-9]* representa todas las palabras que empiezan por una
letra minscula o mayscula seguida de 0 o ms letras o dgitos, como por
ejemplo "v1", "indice", "maximo", "D".

+ Indica 1 ms ocurrencias de la expresin que le precede.

x+ representa todas las palabras formadas por "x", por ejemplo "x", "xx", "xxx".
[0-9]+ representa los nmeros de uno o ms dgitos, por ejemplo "12", "465",
"000", "097".

23
Prcticas de compiladores 2004-2005

Los patrones de Lex/Flex (IV)


Metacaracteres (iii)

| Identifica la expresin que le precede o la que le sigue.

A|B representa la letra "A" o la letra "B". Este patrn se comporta de la misma
manera que el patrn [AB].

"..." Representa lo que est entre las comillas literalmente. Los metacaracteres pierden
su significado excepto "\".
El metacaracter \ si va seguido de una letra minscula se asume que es una
secuencia de escape de C, como por ejemplo el tabulador \t. Si no va seguido de
minscula, \ se utiliza para quitar el significado especial de los metacaracteres, por
ejemplo \* representa un asterisco.

"/*" representa a la agrupacin de caracteres "/*".

() Agrupan expresiones.

(ab|cd)+r representa "abr", "ababr", "cdr", "cdcdr", abcdr, etc.

24
Prcticas de compiladores 2004-2005
Los patrones de Lex/Flex (V)
Metacaracteres (iv)

{ nombre } Un nombre encerrado entre llaves significa al expansin de la definicin de


"nombre".
En la seccin de definiciones se pueden definir expresiones regulares y
asignarles un nombre. Por ejemplo:

DIGITO [0-9]
LETRA [a-zA-Z]

Posteriormente, cualquier aparicin de {DIGITO} se sustituye por la expresin


regular [0-9], y {LETRA} por [a-zA-Z].

La expresin regular de todas las palabras que empiezan por una letra
minscula o mayscula seguida de 0 o ms letras o dgitos:

[a-zA-Z]([0-9]|[a-zA-Z])*

es idntica a:

{LETRA} ({DIGITO}|{LETRA})*

25
Prcticas de compiladores 2004-2005

Los patrones de Lex/Flex (VI)


Cmo se identifican los patrones en la entrada (i)

El analizador busca en la entrada cadenas de caracteres que concuerden con


alguno de los patrones.

Si se encuentra concordancia con ms de un patrn, se selecciona el patrn ms


largo.
Por ejemplo, si se definen las reglas:

begin { return TOK_BEGIN; }


end { return TOK_END; }
[a-z]+ { return TOK_ID;}

La entrada beginend se identificar como TOK_ID.


Durante el anlisis de la entrada, concuerdan dos patrones, el de TOK_BEGIN y el
de TOK_ID, hasta que se lee la segunda e, en ese momento se descarta el
patrn correspondiente a TOK_BEGIN, y se selecciona el patrn de TOK_ID que
es ms largo.
(Se recomienda construir un analizador lxico de prueba)

26
Prcticas de compiladores 2004-2005
Los patrones de Lex/Flex (VII)
Cmo se identifican los patrones en la entrada (ii)

Si hay concordancia con varios patrones, y adems de la misma longitud, se elige


el patrn que est situado primero en la seccin de reglas dentro del fichero de
especificacin Lex/Flex. Por lo tanto, es determinante el orden en que se colocan
las reglas.
Por ejemplo, si se definen las reglas:

[a-z]+ { return TOK_ID;}


begin { return TOK_BEGIN; }
end { return TOK_END; }

La entrada begin se identificar como TOK_ID porque hay concordancia con dos
patrones, el de TOK_BEGIN y el de TOK_ID, pero el patrn de TOK_ID aparece
antes en el fichero de especificacin.

Al procesar con Lex/Flex estas reglas, se muestra un mensaje en el que se indica


que las reglas segunda y tercera nunca se van a identificar.

(Se recomienda construir un analizador lxico de prueba)

27
Prcticas de compiladores 2004-2005

Los patrones de Lex/Flex (VIII)


Cmo se identifican los patrones en la entrada (iii)

En el ejemplo anterior, para que se identifiquen las palabras reservadas begin y


end correctamente, y no como identificadores, se deben colocar sus
correspondientes reglas antes de la regla de los identificadores, de la siguiente
manera:
begin { return TOK_BEGIN; }
end { return TOK_END; }
[a-z]+ { return TOK_ID;}

Cuando se ha determinado el patrn que concuerda con la entrada, el texto del


token se almacena en la variable interna de Lex/Flex yytext que es un char*, y
la longitud se almacena en la variable entera yyleng.

28
Prcticas de compiladores 2004-2005
Tercer ejemplo (I)
Enunciado

Disear un fichero de especificacin Lex/Flex, ej3.l, usando como gua el fichero


de especificacin del segundo ejemplo, para construir un analizador lxico que se
ajuste a los siguientes requisitos.

Los tokens que debe reconocer el analizador lxico son:


TOK_ID: Palabra formada por letras maysculas o minsculas y dgitos del 0 al 9, y
cuyo carcter inicial es una letra.
TOK_NUM: palabra formada por dgitos del 0 al 9.
La definicin de los tokens se realiza en el fichero tokens_ej3.h.

Las acciones que debe realizar el analizador lxico cuando reconozca alugn token
son las siguientes:
Cuando se reconozca un identificador se mostrar el mensaje TOK_ID
Cuando se reconozca un nmero se mostrar el mensaje TOK_NUM.

Compilar la especificacin Lex y generar el ejecutable.

29
Prcticas de compiladores 2004-2005

Tercer ejemplo (II)


Realizacin de pruebas

variableUno Se identifica un token de tipo TOK_ID


TOK_ID Se muestra mensaje TOK_ID

Elemento88A Se identifica un token de tipo TOK_ID


TOK_ID Se muestra mensaje TOK_ID
1234 Se identifica un token de tipo TOK_INUM
TOK_NUM Se muestra mensaje TOK_NUM

44pipas Se identifican los tokens TOK_NUM y TOK_ID


TOK_NUM Observar que ambos tokens se reconocen aunque
TOK_ID no estn separados.
Se muestran los mensajes correspondientes.

_$$ No se identifica ningn token


_$$ Se muestra la entrada (accin por defecto)

^Z/^D Fin de la entrada


Windows / Linux

Texto azul: entrada del usuario


Texto rojo: respuesta del analizador
30
Prcticas de compiladores 2004-2005
Los tokens del lenguaje ASPLE (I)
Identificacin

Los tokens se identifican a partir de la gramtica.


Todo lo que aparece literalmente en las partes derechas de las reglas de la
gramtica:
palabras reservadas:
begin else false input ref true
bool end function int return while
do fi if output then

smbolos simples:
+ - * ( ) ; , = >
smbolos compuestos:
<= :=

Identificadores: cadenas de caracteres alfanumricos, comenzando siempre con una


letra (entendiendo carcter alfanumrico cualquier letra minscula o mayscula, o
cualquier dgito entre el 0 y el 9).

Constantes enteras: cadenas de dgitos entre el 0 y el 9.


33
Prcticas de compiladores 2004-2005

Fichero de especificacin Lex/Flex para el lenguaje ASPLE (I)


Construccin

Partiendo del tercer ejemplo visto anteriormente se construir la especificacin


Lex/Flex para el lenguaje ASPLE realizando las siguientes tareas:
modificar el fichero tokens.h introduciendo una directiva #define por cada uno de los
tokens del lenguaje ASPLE.
Hacer una copia del fichero ej2.l en un nuevo fichero asple.l.
En la seccin de definiciones del fichero asple.l incluir las definiciones de las
expresiones regulares que se van a utilizar para los patrones de los tokens de tipo
identificador y constante entera.
En la seccin de reglas del fichero asple.l incluir una regla para cada token, en cuya
accin se devuelva el token. Tener en cuenta el orden de las reglas (ver siguiente
transparencia).
En la seccin de funciones de usuario del fichero asple.l modificar la funcin main
para que muestre un mensaje por pantalla cada vez que reciba un token de la funcin
yylex(). El mensaje contiene dos campos, el primero es una cadena que decribe el
tipo de token segn la siguiente lista:
ID para los identificadores
KEYWORD para todas las palabras reservadas
NUM para los nmeros
El segundo campo del mensaje es el nmero del token correspondiente segn las
definiciones contenidas en el fichero tokens.h.

36
Prcticas de compiladores 2004-2005
Fichero de especificacin Lex/Flex para el lenguaje ASPLE (II)
El orden de las reglas

El orden de las reglas es importante cuando se identifica en la entrada una cadena


de caracteres que concuerda con dos patrones de la misma longitud ya que se
selecciona la regla que aparece primero en el fichero de especificacin Lex/Flex.
Por ejemplo, las palabras reservadas (begin, bool, call, ...) concuerdan a la vez con
dos patrones:
el patrn que define la propia palabra reservada
el patrn que define a los identificadores
Como ambas concordancias son de la misma longitud, si la primera regla que se
sita en la seccin de reglas fuera la correspondiente a los identificadores, nunca
se detectaran en la entrada las palabras reservadas porque siempre seran
consideradas como identificadores. La solucin es situar primero las reglas de las
palabras reservadas.
Cuando ocurre una situacin como la descrita en el prrafo anterior, al compilar la
especificacin, se recibe el aviso de que hay patrones que nunca se van a
reconocer.
Realizar la siguiente prueba: en el fichero asple.l situar el patrn de los
identificadores delante de los patrones de las palabras reservadas. Qu ocurre
cuando la entrada es, por ejemplo, la palabra begin?.
37
Prcticas de compiladores 2004-2005

Gestin de los espacios en blanco (I)

Otras de las funciones del analizador morfolgico adems de identificar los tokens
en el fichero de entrada, es ignorar los espacios en blanco, los tabuladores y los
saltos de lnea que aparecen en la entrada.
Una solucin para incorporar esta funcionalidad es:
disear el patrn que identifique los caracteres que se quieran ignorar.
Incorporar una regla para dicho patrn y que tenga como accin no hacer nada, que
en Lex/Flex se especifica con un punto y coma en el lugar del cdigo C.

42
Prcticas de compiladores 2004-2005
Control de la posicin de los tokens en el fichero de entrada (I)

El analizador lxico es la parte del compilador que accede al fichero de entrada y


por lo tanto es el que conoce la posicin (lnea y carcter) de los tokens en el
fichero de entrada. Esta posicin es muy importante para informar de los errores de
compilacin ya que los errores deben de ubicarse en una posicin del fichero de
entrada.
Para conocer la posicin de los tokens en el fichero de entrada se pueden utilizar
dos variables, una para almacenar la lnea y otra para el carcter dentro de la
lnea. Ambas variables se pueden declarar en la seccin de definiciones del fichero
de especificacin Lex/Flex, por ejemplo:

%{
int lineno = 1; /* nmero de lnea */
int charno = 0; /* nmero de carcter */
%}

44
Prcticas de compiladores 2004-2005

Control de la posicin de los tokens en el fichero de entrada (II)

La actualizacin de las variables se realiza en el cdigo de las reglas. Por ejemplo:


cuando se identifique la palabra clave begin, se avanza en la posicin del fichero 5
caracteres (tambin se puede usar la variable yyleng para conocer cuntos caracteres
se avanzan en a entrada).
Cuando se encuentra un identificador o un nmero entero, se puede utilizar la variable
interna de Lex/Flex yyleng para incrementar el nmero de carcter.
cuando se identifica un tabulador o un espacio en blanco, se avanza en la posicin del
fichero 1 carcter.
cuando se encuentra un salto de lnea se incrementa en 1 el nmero de lnea, y se
reinicia a 0 el nmero de carcter dentro de la lnea.

Puede observarse que la accin asociada a los caracteres tabulador y espacio en


blanco, es diferente a la asociada al carcter de salto de lnea. Por este motivo,
aunque los tres tipos de carcter deben ser igualmente ignorados, se utilizan reglas
diferentes para poder incorporar acciones distintas.

45
Prcticas de compiladores 2004-2005
Gestin de los comentarios (I)

Para gestionar los comentarios es necesario:


disear el patrn que identifique el comentario.
Incorporar una regla para dicho patrn y que tenga como accin incrementar en 1 el
nmero de lnea y reiniciar a 0 el nmero de carcter dentro de la lnea.

47
Prcticas de compiladores 2004-2005

Gestin de errores (I)

Si no se reconoce ninguno de los patrones diseados, la opcin por defecto es


copiar la entrada en la salida. Para evitar este comportamiento, se puede definir un
tipo de token de error, de manera que cuando no se identifique ninguno de los
tokens del lenguaje, se considere que se ha encontrado un error, y tenga como
accin asociada devolver ese token de errror.

Para incorporar esta funcionalidad:


definir en el fichero tokens.h el nuevo token de error con valor -1.
disear el patrn que identifique el token de error, por ejemplo con el metacaracter .
Incorporar una regla para dicho patrn y que tenga como accin devolver el token
definido en el fichero tokens.h

En la funcin main se incorpora una nueva comprobacin para el error.

49
Prcticas de compiladores 2004-2005
Ficheros de entrada/salida de Lex/Flex

FILE* yyin
es el fichero de entrada, del que lee la funcin yylex().
Por defecto es la entrada estndar.
El usuario puede asignarle cualquier variable de tipo FILE*, por supuesto, antes de que
se inicie el anlisis, es decir, antes de invocar a la funcin yylex().

FILE* yyout
es el fichero de salida, en el que se escribe la regla por defecto (cuando no concuerda
ningn patrn se copia la entrada en la salida)
Por defecto es la salida estndar.
El usuario puede asignarle cualquier variable de tipo FILE*.

51
Prcticas de compiladores 2004-2005

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