Você está na página 1de 13

Analizador Lxico Bsico en C#

La primera sesin una de las fases iniciales en el proceso de compilacin es el anlisis


lxico. En esta prctica vamos a construir un analizador lxico bsico para un lenguaje
llamado OperA, este lenguaje permite la definicin de operaciones aritmticas bsicas,
utilizando variables, nmeros, signos de agrupacin y operadores.
Componentes Lxicos
Siempre que se va a disear un nuevo lenguaje la primera fase es definir formalmente los
componentes lxicos validos para el mismo, en nuestro caso son:

Un nmero entero es una secuencia de dgitos


Un identificador es una secuencia de letras y luego dgitos o letras
Los espacios son ignorados
Los operadores son multiplicativos y de adicin
Los signos de agrupacin son parntesis derecho e izquierdo.

Formalmente utilizando expresiones regulares se definiran

Token

Patrn

OPERADD

[+-]

OPERMUL

[*/]

NUMEINT

[0-9]+

IDENT

[a-zA-Z]+

AGRUP

[()]

Requerimientos funcionales del analizador lxico


R1 : Generar los Tokens del lenguaje OperA

Entradas : Un texto de entrada


Salidas : Una coleccin de smbolos con los tokens encontrados en el texto de entrada.
Construyendo el Analizador Lxico
Un diagrama de clases para nuestro sistema puede ser:

Un analizador lxico puede generar 0 o ms smbolos, cada smbolo debe corresponder a un


token especfico.
Anlisis de las funciones a realizar
Obtener un Token
Un analizador lxico en esencia debe leer carcter por carcter de la entrada de datos hasta
identificar un Token vlido, retornar dicho token y continuar con el proceso hasta encontrar
el fin de la entrada de datos.
El algoritmo general para el mtodo que obtiene un token es:

Obtenga un carcter del texto de entrada

Si es un carcter en blanco ignrelo

Si es un operador(matemtico o de agrupacin) retorne el token correspondiente

Si es un digito siga leyendo caracteres del texto de entrada hasta encontrar un


carcter que no sea digito y al terminar retorne el token de numero entero

Si es una letra (y es la primera) siga leyendo mientras sea letra o nmero. Al


terminar retorne el token de identificador

Obtener Lista de Tokens


Otra funcin del analizador lxico es obtener todos los tokens existentes en el archivo
fuente.
El algoritmo general para el mtodo que obtiene la lista de tokens es: Mientras no se
obtenga el token de fin

Obtener token con el mtodo anterior


Almacenar el token en la lista

Implementacin del Componente Analizador Lexico para OperA


Para la implementacin utilizaremos el lenguaje de programacin C# y el Visual Studio.
Creando una dll para el analizador
1. Ingrese al Visual Studio

Una vez en el entorno de desarrollo vamos a crear un componente (dll) con las clases para
el analizador Lxico.
Seleccione File/New/Project

Configure el proyecto como se muestra en la siguiente grfica:

Al ingresar se aparece una plantilla con cdigo en C#.


Vamos a adicionar un enum (enumeracin), que representa los tokens validos en el
lenguaje, este se define antes de la clase pero en el mismo Namespace.

Luego de la definicin del enum vamos a adicionar la clase Smbolo como se muestra a
continuacin:

Por ltimo se implementa la clase AnaLexOperA

Ahora implementamos en esta clase la propiedad que permite recorrer la cadena de


entrada (con el cdigo fuente) al retornar el carcter actual de la entrada.

El siguiente mtodo identifica un token en la entrada y devuelve un objeto simbolo con el


token encontrado. Puede verse que es una implementacin a fuerza bruta

Por ltimo implementamos el mtodo que retorna todos los tokens encontrados.

Compile la aplicacin
Creando Un cliente para la dll
Vamos a crear una aplicacin de consola que permita verificar el funcionamiento de la dll
anterior.
Cree un nuevo proyecto como se muestra a continuacin

En este programa agregue la librera que creamos en la primera parte, busque en la


ventana Solutions Explorer la pestaa References y de clic derecho Add Reference .NET
Assembly Browser y ubique la carpeta bin/debug del proyecto AnaLexperA y seleccione la
dll.

En la ventana que aparece seleccione la pestaa Browse y ubique la dll generada en la


primera parte.

Agregue el namespace donde est el analizador lxico:

using mnAnaLexOperA;
Edite el siguiente cdigo
namespace ConsolaOperA
{
class MainClass
{
public static void Main(string[] args)
{ string codigoFuente="(35+87*59)

76

";

AnaLexOperA analex= new AnaLexOperA(codigoFuente);


foreach(Simbolo s in analex.GetSimbolos())
{
switch((int)s.Token)
{
case (int)Tokens.IDENT:{Console.WriteLine("IDENT");break;}
case (int)Tokens.OPERADD:{Console.WriteLine("OPERADD");break;}
case (int)Tokens.OPERMUL:{Console.WriteLine("OPERMUL");break;}
case (int)Tokens.NUMEINT:{Console.WriteLine("NUMEINT");break;}
case (int)Tokens.OPERAGRU:{Console.WriteLine("OPERAGRU");break;}
case (int)Tokens.ERROR:{Console.WriteLine("ERROR");break;}
}

Console.ReadLine();
}
}
}

public Simbolo GetToken()


{
char carActual = GetCaracter;
if(indice >textoEntrada.Length || carActual == @)
return new Simbolo (Tokens.FIN, fin);
switch (carActual)
{
case : { break; }
case \t': { break; }
case \n': { break; }
case +': {return new Simbolo(Tokens.OPERADD,+);}

case -: { return new Simbolo(Tokens.OPERADD,-); }


case *': { return new Simbolo(Tokens.OPERMUL,*); }
case /':
{
if (GetCaracter == /)
{
while (carActual != \n && carActual != @)
{
carActual = GetCaracter;
//System.Windows.Forms.MessageBox.Show(carActual.ToString());
}
break;
}
return new Simbolo(Tokens.OPERMUL,/);
}
case (: { return new Simbolo(Tokens.OPERAGRU,(); }
case )': { return new Simbolo(Tokens.OPERAGRU,)); }
case D':
case d':
{
carActual = GetCaracter;
if (carActual == o || carActual == O)
{
return new Simbolo(Tokens.PALABRARES, do);
}
break;
}
case W':
case w':
{
System.Windows.Forms.MessageBox.Show(carActual.ToString());
carActual = GetCaracter;
string palabraWhile = hile;
string palabraWHILE = HILE;
for (int i = 0; i < palabraWhile.Length; i++)
{

//System.Windows.Forms.MessageBox.Show(carActual.ToString() + " " +


palabraWHILE[i].ToString() + " " + palabraWhile[i].ToString());
if (carActual != palabraWhile[i] && carActual != palabraWHILE[i])
{
break;
}
carActual = GetCaracter;
}
return new Simbolo(Tokens.PALABRARES,"while");
}
default:
{
if (Char.IsDigit(carActual))
{
string digito = "";
while (Char.IsDigit(carActual))
{
digito += carActual.ToString();
carActual = GetCaracter;
MessageBox.Show(carActual.ToString());
}
if (carActual == 'E')
{
string notacionCient = "";
notacionCient += carActual.ToString();
carActual = GetCaracter;
MessageBox.Show(carActual.ToString());
if (carActual == '-' || carActual == '+')
{
notacionCient += carActual.ToString();
carActual = GetCaracter;
if (char.IsDigit(carActual))
{
MessageBox.Show(carActual.ToString());
while (Char.IsDigit(carActual))
{
notacionCient += carActual.ToString();
carActual = GetCaracter;
MessageBox.Show(carActual.ToString());
}

digito += notacionCient;
MessageBox.Show(digito.ToString());
return new Simbolo(Tokens.NOTACIENT, digito);
}
}
else
{
return new Simbolo(Tokens.ERROR, "");
}
}
if (indice < textoEntrada.Length || carActual != '@')
indice;
return new Simbolo(Tokens.NUMEINT, digito);
}
else
{
if (Char.IsLetter(carActual))
{
string palabra = "";
while (Char.IsLetter(carActual) || Char.IsDigit(carActual))
{
palabra += carActual.ToString();
carActual = GetCaracter;
}
if (indice < textoEntrada.Length || carActual != '@')
indice;
return new Simbolo(Tokens.IDENT,palabra);
}
else
{
return new Simbolo(Tokens.ERROR,"");
}
}
}
}
return new Simbolo(Tokens.VACIO,"");

Você também pode gostar