Un
analizador de léxico tiene como función principal el tomar secuencias de
caracteres o símbolos del alfabeto del lenguaje y ubicarlas dentro de
categorías, conocidas como unidades de léxico. Las unidades de léxico son
empleadas por el analizador gramatical para determinar si lo escrito en el
programa fuente es correcto o no gramaticalmente. Algunas de las unidades de
léxico no son empleadas por el analizador gramatical sino que son descartadas o
filtradas. Tal es el caso de los comentarios, que documentan el programa pero
que no tienen un uso gramatical, o los espacios en blanco, que sirven para dar
legibilidad a lo escrito.
En
la terminología empleada en la construcción de un analizador de léxico se
encuentran los siguientes términos.
Patrón
Representa
la regla para que una secuencia de caracteres sea considerada cierta unidad de
léxico. Ejemplo: El patrón para un identificador de Pascal es:
Una
letra seguida por letras, dígitos o guiones (_)
Lexema
El
valor actual de un conjunto de caracteres que satisfacen un patrón.Ejemplo:
Este_es_1_ejemplo
Este es el lexema que
satisface el patrón de un identificador
Token o
Ficha
El valor asociado a una categoría o unidad de léxico. Se representa como un número entero o una constante de un byte. Ejemplo: el token de un identificador puede ser 1 ó id (si id fue definida como 1).
El compilador revisa y controla que las "palabras" estén
bien escritas y pertenezcan a algún tipo de token
(cadena) definido dentro del lenguaje, como por ejemplo que sea algún tipo de
palabra reservada, o si es el nombre de una variable que este escrita de
acuerdo a las pautas de definición del lenguaje.
El
analizador lexico que se realizara mas adelante
durante el proceso de la creación del proyecto se encarga de realizar las
siguientes operaciones:
Reconoce las sig. Como palabras reservadas:
"include","int","char","float","const","void","for","if","do","printf",
"while","clrscr","main","alee","flee","getch","getche","strcpy","qordena","strlen",
"gotoxy","llee","ellee","mayus","break","return","stdio.h","stdlib.h","conio.h","dos.h",
"string.h","ctype.h","strcmp","else"};
Reconoce los sig.
Tipos de datos
{"int","char","float","void","const"};
El rol del analizador de Léxico
Aunque
el analizador de léxico es la primera etapa del proceso de compilación, no es
quien lo inicia. Pudiera considerarse que el analizador de léxico hace su
procesamiento y envía sus resultados al analizador gramatical, como secuencialmente se aprecia en el proceso de compilación; no
es así: La compilación empieza con el analizador gramatical quien solicita un token para realizar su trabajo; el analizador de léxico reune símbolos y envía el token
correspondiente a la unidad de léxico que conformó al analizador gramatical y
espera una nueva solicitud de token. Como se aprecia
en la figura siguiente, el analizador de léxico está supeditado por el
analizador gramatical.
Durante
estas etapas se tiene comunicación con la tabla de símbolos que concentra
información de las entidades empleadas en el programa.
Descripcion de Patrones
Un patrón
se puede describir:
1.
Mediante una descripción informal, en donde se emplea el lenguaje natural para
describir el comportamiento de la regla de léxico. Por ejemplo: un número
entero es una secuencia de uno o más dígitos del 0 al 9. O un identificador es
una letra seguida de letras, dígitos o guiones de subrayar. La descripción
informal es útil sólo entre humanos; computacionalmente
aún no hay herramientas para construir sobre ellas analizadores de léxico.
2.
Utilizando expresiones regulares. Una expresión regular es una notación formal
que utiliza operaciones sobre el alfabeto de un lenguaje. Por ejemplo, se puede
definir que un identificador es:
{letra} ({letra} | {dígito} |
{guión})*
que interpreta como un elemento del conjunto letra seguido de cero
o mas veces (la cerradura Kleene, representada por el
asterisco) de una letra, dígito o guión (la selección representada por la barra
vertical).
Esta
notación es formal y computacionalmente útil para
construir analizadores de léxico empleando la herramienta LEX.
3.
Utilizando autómatas finitos (diagramas de transición o diagramas sintácticos),
que son representaciones gráficas de las relaciones entre conjuntos de símbolos
(aristas) por medio de estados, a los cuales pueden llegarse o transitarse por
ellos al encontrar un símbolo perteneciente a un conjunto. El siguiente
diagrama puede ser la representación de un identificador:
La utilización del diagrama sirve para aclarar las posibilidades de acción en un patrón y puede manipularse computacionalmente.
Diagramas
de Transición
Un diagrama de transición es
una representación gráfica donde se tiene un conjunto de estados, los cuales
pueden ser:
·
iniciales
·
finales
·
intermedios
los cuales pueden tener una o más
salidas hacia otro estado.
Los estados se relacionan
entre sí con flechas con un nombre (el caracter o conjunto
de caracteres que provoca la transición de un estado a otro).
Un estado final se representa con :
que también recibe el nombre de
estado de aceptación.
Para construir un diagrama de
transición se debe tener presente:
·
A cada estado debe llegarse con el mismo conjunto de caracteres
en todas las ocasiones en que haya un transición.
·
Para llegar a un estado de aceptación debe existir una
transición sobre el caracter que rompe el patrón de
la unidad de léxico.
Cuando se construye un
analizador de léxico utilizando diagramas de transición para la especificación
de los patrones, se realiza un único diagrama que, a partir del estado 0, tiene
diversas transiciones a cada uno de los patrones de las unidades de léxico que
deba reconocer. Cada patrón posee un caracter
selector, que permite reconocer de manera única el patrón que deba aplicarse.
Por ejemplo, si queremos
reconocer identificadores, comentarios apegados a las reglas del lenguaje C y
el fin de archivo, podriamos contruir
el siguiente diagrama:
Analizador_de_Lexico
INICIO
Estado=0
C=Inspecciona()
Cont=0
Nuevo_Estado=TABLA[Estado, C]
MIENTRAS Nuevo_Estado no sea Estado_Final
REPITE
Avanza()
C=Inspecciona()
Estado=Nuevo_Estado
Nuevo_Estado=TABLA[Estado, C]
Cont=Cont+1
FREPITE
SI
Cont es 0
ENTONCES
Avanza()
FSI
Regresa Token (Estado_Nuevo)
FIN