jueves, 14 de enero de 2010

Calculo de Iniciales

Gramatica
NT = E,E',T,T',F
T = +,*,(,),#,i

E -> TE'
E' -> +TE'
E'-> #
T -> FT'
T' -> *FT'
T' -> #
F -> (E)
F -> i


Codigo de Calculo de Iniciales

Archivo CPP

#include "iniciales.h"

char NoTerminales[ 100 ];
char Terminales[ 100 ];

int main( int argc, char** argv )
{
CIniciales calcIni;
fstream Salida;
char buffIni[ 100 ] = "";
int i;
cout<<"**********Calculo de Iniciales**********"<
calcIni.SetFname( "gramatica.txt" );//Nombre del archivo

if( calcIni.CargarGramatica() == NOABRE )
cout << "error al abrir la gramatica!" << endl;


else
{ char nt[ 100 ], alf[ 100 ], ini[ 100 ];

for( i=0; i <= calcIni.NumProducciones(); i++ ) // calculo de los iniciales
{
calcIni.ObtenerProduccion( nt, alf, ini, i );

if( !strlen( ini ) ) calcIni.CalcIniciales( i, buffIni );
}

Salida.open( SALIDA, ios::out );

if( Salida.fail() ) cout << "ERROR! No se puede guardar el archivo de iniciales" << endl;

else
{
for( i=0; i <= calcIni.NumProducciones(); i++ )
{
calcIni.ObtenerProduccion( nt, alf, ini, i );
Salida << nt << " -> " << ini << endl;
cout<< nt << " -> " << ini << endl< }

cout << "Simbolos Iniciales Calculados" << endl;
}
}

if( argc > 1 ) cin.sync(), cin.get();

cout << 0;

return 0;
}

int BuscarTerminal( const char* T )
{
int i;

for( i=0; Terminales[ i ]; i++ ) if( Terminales[ i ] == T[0] ) return i;

return ERR_NO_ENCONTRADO;
}

CIniciales::CIniciales()
{
this-> prod = NULL;
this-> ultimaProd = -1;
}

CIniciales::~CIniciales()
{
int i = this-> ultimaProd;

if( this-> prod ) // si es distinto de NULL
{
for( ; i >= 0; i--)
{
delete[] this-> prod[ i ].Nterminal;
delete[] this-> prod[ i ].Alfa;
delete[] this-> prod[ i ].inicial;
}

delete[] this-> prod;
}
}

inline int CIniciales::NumProducciones() { return this-> ultimaProd; }

inline int CIniciales::SetFname( const char* File )
{ strcpy( this-> archivo, File ); return 0; }

int CIniciales::CargarGramatica()
{
char buffer[ MAX_BUFF ];
char Nt[ 20 ], alf[ 100 ];
char auxNt[ 20 ], auxAlfa[ 100 ], auxIni[ 3 ];
int i = 0, j = 0, ind;
fstream fgrama;

fgrama.open( this-> archivo, ios::in );
if( fgrama.fail() ) return NOABRE;

fgrama.getline( buffer, MAX_BUFF );

while( buffer[ i++ ] != '=' ) ;

i++;

while( buffer[ i ] ) // obtener no terminales
{
if( buffer[ i ] != ' ' ) NoTerminales[ j++ ] = buffer[ i ];

i++;
}

NoTerminales[ j ] = 0;

fgrama.getline( buffer, MAX_BUFF );

i = 0; j = 0;

while( buffer[ i++ ] != '=' ) ;

i++;

while( buffer[ i ] ) // se obtienen terminales
{
if( buffer[ i ] != ' ' && buffer[ i ] != ',' ) Terminales[ j++ ] = buffer[ i ];

i++;
}

Terminales[ j ] = 0;

while( !fgrama.eof() ) // producciones
{
fgrama.getline( buffer, MAX_BUFF );

if( !strlen( buffer ) ) continue;

for( j=0, i=0; buffer[ i ]; i++ ) // obtiene el no terminal
{
if( buffer[ i ] == ' ' ) continue;

if( buffer[ i ] != '-' && buffer[ i+1 ] != '>' )
{
Nt[ j++ ] = buffer[ i ];
continue;
}

else
{
Nt[ j ] = 0;
i += 2;
break;
}
}

for( j=0; buffer[ i ]; i++ ) // obtiene el alfa
{
if( buffer[ i ] == ' ' ) continue;

alf[ j++ ] = buffer[ i ];
}

alf[ j ] = 0;

ind = this-> BuscarProduccion( Nt ); // busca una produccion

if( ind != ERR_NO_ENCONTRADO )
{
this-> ObtenerProduccion( auxNt, auxAlfa, auxIni, ind );

strcat( auxAlfa, "," ); strcat( auxAlfa, alf );

this-> ModificarProduccion( Nt, auxAlfa, "", ind );
}

else this-> AgregarProduccion( Nt, alf, "" );

}

fgrama.close();

return 0;
}

int CIniciales::CalcIniciales( int indice, char* lista_ini )
{
int i, j, tam, ind, k;
char temp[ 5 ];

tam = strlen( this-> prod[ indice ].Alfa );
k = strlen( lista_ini );

for( i=0, j=0, k=0; i < tam; i++ )
{
temp[ j ] = this-> prod[ indice ].Alfa[ i ];

if( this-> prod[ indice ].Alfa[ i+1 ] == '\'' )
{
temp[ j++ ] = this-> prod[ indice ].Alfa[ i++ ];
}

temp[ ++j ] = 0;

ind = BuscarTerminal( temp );

if( ind != ERR_NO_ENCONTRADO ) // si es terminal, lo agrega como inicial
{
lista_ini[ k++ ] = Terminales[ ind ];
lista_ini[ k++ ] = ',';
lista_ini[ k ] = 0;
}

else // si es un no terminal, busca sus iniciales
{
ind = this-> BuscarProduccion( temp );

this-> CalcIniciales( ind, lista_ini );
k = strlen( lista_ini );
}

for( i++; this-> prod[ indice ].Alfa[ i ]; i++ )
{
if( this-> prod[ indice ].Alfa[ i ] == ',' ) break;
}

j = 0;
}

if( this-> prod[indice].inicial ) delete[] this-> prod[ indice ].inicial;

if( lista_ini[ k-1 ] == ',' ) lista_ini[ k-1 ] = 0;

this-> prod[ indice ].inicial = new char[ strlen( lista_ini )+1 ];
strcpy( this-> prod[ indice ].inicial, lista_ini );

return 0;
}

int CIniciales::AgregarProduccion( const char* Nterm, const char* alfa, const char* Inicial )
{
int i = 0;
PRODUCCION *temp;

this-> ultimaProd++;

temp = new PRODUCCION[ this-> ultimaProd+1 ];

if( !temp ) return ERR_ASIGNACION_DE_MEMORIA;

for( ; i < this-> ultimaProd; i++ )
{
temp[ i ].Nterminal = this-> prod[ i ].Nterminal;
temp[ i ].Alfa = this-> prod[ i ].Alfa;
temp[ i ].inicial = this-> prod[ i ].inicial;
}

delete[] this-> prod;

temp[ i ].Nterminal = new char[ strlen( Nterm ) +1 ];
temp[ i ].Alfa = new char[ strlen( alfa ) +1 ];
temp[ i ].inicial = new char[ strlen( Inicial ) +1 ];

if( !temp[ i ].Nterminal || !temp[ i ].Alfa || !temp[ i ].inicial )
return ERR_ASIGNACION_DE_MEMORIA;

strcpy( temp[ i ].Nterminal, Nterm );
strcpy( temp[ i ].Alfa, alfa );
strcpy( temp[ i ].inicial, Inicial );

this-> prod = temp;

return this-> ultimaProd;
}

int CIniciales::BuscarProduccion( const char* Nterm )
{
int i = 0;

while( i <= this-> ultimaProd )
{
if( !strcmp( this-> prod[ i ].Nterminal, Nterm ) ) return i;
i++;
}

return ERR_NO_ENCONTRADO;
}

int CIniciales::ModificarProduccion( const char* Nterm, const char* alfa, const char* Inicial, int indice )
{
if( indice < 0 || indice > this-> ultimaProd ) return ERR_FUERA_DE_RANGO;

delete[] this-> prod[ indice ].Nterminal;
delete[] this-> prod[ indice ].Alfa;
delete[] this-> prod[ indice ].inicial;

this-> prod[ indice ].Nterminal = new char[ strlen( Nterm ) +1 ];
this-> prod[ indice ].Alfa = new char[ strlen( alfa ) +1 ];
this-> prod[ indice ].inicial = new char[ strlen( Inicial ) +1 ];

if( !prod[ indice ].Nterminal || !prod[ indice ].Alfa || !prod[ indice ].inicial )
return ERR_ASIGNACION_DE_MEMORIA;

strcpy( this-> prod[ indice ].Nterminal, Nterm );
strcpy( this-> prod[ indice ].Alfa, alfa );
strcpy( this-> prod[ indice ].inicial, Inicial );

return indice;
}

int CIniciales::ObtenerProduccion( char* Nterm, char* alfa, char* Inicial, int indice )
{
if( indice < 0 || indice > this-> ultimaProd ) return ERR_FUERA_DE_RANGO;

strcpy( Nterm, this-> prod[ indice ].Nterminal );
strcpy( alfa, this-> prod[ indice ].Alfa );
strcpy( Inicial, this-> prod[ indice ].inicial );

return indice;
}

Archivo H

#ifndef INICIALES_H
#define INICIALES_H
#include
#include
#include
using namespace std;

#ifndef MAX_PATH
#define MAX_PATH 256
#endif

#define MAX_BUFF 256

#define SALIDA "iniciales.txt"

#define ERR_ASIGNACION_DE_MEMORIA -1
#define NOABRE -2
#define ERR_NO_ENCONTRADO -3
#define ERR_FUERA_DE_RANGO -4


typedef struct _PRODUCCION
{
char *Nterminal;
char *Alfa;
char *inicial;

} PRODUCCION;

// clase para el manejo de archivo
class CIniciales
{
private:
PRODUCCION *prod;
int ultimaProd;
char archivo[ MAX_PATH ];

public:
CIniciales();
~CIniciales();

int SetFname( const char* File );
int CalcIniciales( int indice, char* lista_ini );
int NumProducciones();

int CargarGramatica();
int AgregarProduccion( const char* Nterm, const char* alfa, const char* Inicial );
int BuscarProduccion( const char* Nterm );
int ModificarProduccion( const char* Nterm, const char* alfa, const char* Inicial, int indice );
int ObtenerProduccion( char* Nterm, char* alfa, char* Inicial, int indice );
};

int BuscarTerminal( const char* T );

#endif

Iniciales Calculados

E -> (,i
E' -> +,#
T -> (,i
T' -> *,#
F -> (,i


Resultado en Consola






No hay comentarios:

Publicar un comentario