JP02 - Analisis Lexicografico
JP02 - Analisis Lexicografico
JP02 - Analisis Lexicografico
El análisis lexicográfico o análisis léxico consiste en el proceso a través del cual el traductor
recibe los símbolos desde el programa fuente.
El programa fuente (PF) es producido por el usuario a través de un software conocido como
editor. Dicho editor usa un formato interno que posibilita su edición visual, específicamente
el editor marca el final de cada línea y el inicio de la siguiente línea a través de 2 caracteres
de control que son CR y LF (códigos ascii 0D y 0A). Estos dos caracteres son ingresados
cuando presionamos la tecla ENTER.
main() {
cout << 4; ---->
}
La implementación del scanner puede ser realizada de forma simple o de forma elaborada,
dependiendo de las necesidades del Lenguaje Fuente.
Podríamos entonces obtener mayor información del token, no solo su nombre sino también
su tipo de símbolo. Igualmente podemos diferenciar un identificador de una palabra
reservada.
scanner() {
token.nombre = “”;
while ( CadFuente[ PosActual ] == ‘ ‘ ) // ignorar espacios en blanco
PosActual ++;
If (CadFuente[ PosActual ] IN [ ‘a’ .. ‘z’] ) { // Si es una letra ==> ID
token = CadFuente[ PosActual ] ;
PosActual ++ ;
while (CadFuente[ PosActual ] IN [ ‘a’ .. ‘z’, ‘0’ .. ‘9’] ) { // Si es letra o digito
token.nombre = token.nombre + CadFuente[ PosActual ] ;
PosActual ++;
}
if ( BuscaTPR( token.nombre ) ) // Devuelve TRUE si es una PR
token.tipo = “PR”; // tipo PALABRA RESERVADA
else
token.tipo = “ID”; // tipo IDENTIFICADOR
}
elseif (CadFuente[ PosActual ] IN [ ‘0’ .. ‘9’ ) { // Si es un digito ==> NUM
token.nombre = CadFuente[ PosActual ] ;
PosActual ++ ;
while (CadFuente[ PosActual ] IN [ ‘0’ .. ‘9’] ) { // Si es digito
token.nombre = token.nombre + CadFuente[ PosActual ] ;
PosActual ++;
}
token.tipo = “NUM”; // tipo NUMERO
}
elseif ( CadFuente[ PosActual ] IN [ ‘+, ‘-’, ‘*’, ‘/’ ] ) { // operador de 1 caracter
token = CadFuente[ PosActual ] ;
token.tipo = “OP”; // tipo OPERADOR
}
else
ErrorLexicografico() ; // Carácter No Valido
}
Podemos resumir los conceptos que hemos utilizado mediante las siguientes definiciones.
Lexema. Es la ocurrencia específica del símbolo. Por ejemplo para el símbolo NUMERO
podemos tener los siguientes lexemas 4, 325, 87, etc. Para el símbolo IDENTIFICADOR
podemos tener los siguientes lexemas: x, suma, a21.
Token. Es el símbolo que entrega el scanner. Al ultimo símbolo entregado por el scanner
se le conoce como el token actual.
Patrón de Formación
Los símbolos generalmente tienen un patrón de formación que caracteriza a todos sus
lexemas. Por ejemplo un nombre de variable debe empezar con una LETRA, luego puede
terminar ahí o bien seguir una secuencia de LETRAS, DIGITOS o bien una combinación
de LETRAS y DIGITOS.
Dicho patrón de formación debe ser expresado en una notación adecuada para que el
scanner lo pueda interpretar. La notación mas utilizada es la expresión regular, que se
vera mas adelante.
Generadores de Scanner. Se dispone de diversos software que automatizan la
construcción del Scanner. Estos software reciben como entrada el patrón de formación,
generalmente denotado como una expresión regular, y producen como salida el código
fuente de una función scanner.
% /* Inclusion de librerias */ %
DIGITO [0-9]
ID [a-z][a-z0-9]*
%%
{DIGITO}+ { printf( "Entero: %s (%d)\n", yytext, atoi( yytext ) ); }
%%
main( int argc, char **argv )
{
++argv, --argc; /* ignora el nombre del programa */
if ( argc > 0 )
yyin = fopen( argv[0], "r" );
else
yyin = stdin;
yylex();
}
Observaciones adicionales.
1. Cuando recorremos la cadena fuente podemos, por ejemplo, apuntar al carácter ‘<’
y entonces podríamos preliminarmente suponer que nos encontramos con el
operador relacional MENOR, pero esto no es necesariamente cierto pues
dependerá de cual es el siguiente carácter. Si el siguiente carácter es ‘=’ o ‘>’ o ‘<’
entonces se trata de otro operador.
2. El scanner solo realiza análisis léxico, es decir identifica y entrega los símbolos
reconocidos al analizador sintáctico. Puede realizar algunas otras tareas
complementarias como eliminar comentarios y cambiar nombres por identificadores,
pero no realiza validaciones sintácticas. Esa tarea le corresponde al analizador
sintáctico.
3. El scanner puede interactuar con el pre procesador. Por ejemplo podría encontrar
la declaración ‘#define DOS 2’ y a partir de ahí cuando encuentre una ocurrencia
de DOS dentro del programa fuente lo reemplazara por 2.
4. El conjunto de símbolos validos dependerá del Lenguaje Fuente, lo que puede ser
valido en un lenguaje puede no serlo en otro. Por ejemplo el operador ‘++’ es
valido en el lenguaje C pero no es valido en algunos otros lenguajes.