Está en la página 1de 5

/* Este programa verifica que las entradas de un programa no contengan

errores de sintaxis elementales, como verificar que las llaves,


corchetes y parentesis se cierren correctamente
*/

// Definicion de constantes simbolicas y encabezados

# define OK 0
# define ERROR -1
# define FALSO 0
# define VERDADERO 1
# define LLENA 1
# define PILAMAX 100
# define ADENTRO 1
# define AFUERA 0
# include <stdio.h>

int superior = -1; // Un par de variables externas

int pila[PILAMAX];

empujar( int nuevo )

// La funcion empujar tiene mete elementos en la pila

{ // abre la funcion empujar

if ( superior + 1 >= PILAMAX )

return( LLENA);

pila[ ++superior ] = nuevo;

return( OK);

} // Cierra la funcion empujar

int extraer()
{ // La funcion extrae elementos de la pila

return( pila[superior--] );

} // Cierra la funcion extraer

int vacio()

{ // Abre vacio
if( superior < 0 )
return(VERDADERO);

return(FALSO);

} // Cierra vacio

// Aqui se define la funcion a la que se hara referencia


// Esta funcion realiza la tarea fundamental de revisar que los
// parentesis se cierren adecuadamente

int Revisa_Parentesis( int datos[])

{ // ABre la funcion Revisa_Parentesis

int i;
int comentario = AFUERA;

/* Esta variable se usa para tener en cuenta siempre si se esta o no dentro de


un
comentario, en caso de estarlo, no debe realizarse nada mas que seguir
leyendo
los caracteres hasta que se encuentre la secuencia de terminacion de
comentario
De entrada se empieza fuera de un comentario */

for ( i = 0; datos[i] != 0; i++ )

// En C++ si es posible declarar la variabl int en la primera parte


// de for; en C la declaracion no puede hacerse en el ciclo

// Este ciclo for pasa por alto los caracteres que no sean parentesis
// Los parentesis de apertura se guardan en una pila

{ // ABre for

switch( datos[i])

{ // ABre switch

case '{':

case '[':

case '(':

if ( AFUERA == comentario )
{
empujar( datos[i]);

break;

case '}':

if ( AFUERA == comentario )

if (vacio() || extraer() != '{')

return (ERROR);
break;

case ']':

if ( AFUERA == comentario )

if (vacio() || extraer() != '[')

return (ERROR);
break;

case ')':

if ( AFUERA == comentario )

if (vacio() || extraer() != '(')

return (ERROR);
break;

case '/':

if ( AFUERA == comentario )

{
if ( '*' == datos[i + 1] )

comentario = ADENTRO;

if (ADENTRO == comentario)

if ( '*' == datos[ i - 1])

comentario = AFUERA;

break;

} // Cierra switch

} // Cierra for

if ( ADENTRO == comentario )

// Es decir, si nunca se cerro un inicio de comentario, entonces es un errror

return (ERROR);

if ( vacio())

return (OK);

return (ERROR);

} // Cierra la funcion Revisa_Parentesis

int main()

{ // Abre main

int cadena[PILAMAX];

int c;
int x = 0;

int j;

printf("\nEste programa funciona como una especie de preprocesador. ");


printf("\nPor favor introduzca una cadena con comentarios y le dire si ");
printf(" los parentesis, corchetes, llaves o comentarios estan bien cerrados o
no.\n");

while( (c = getchar()) != EOF )


cadena[ x++ ] = c;

j = Revisa_Parentesis( cadena);

if ( OK == j )
printf("\nLos parentesis estan bien escritos.\n");

else

if( ERROR == j )

printf("\nLos parentesis estan mal escritos.\n");

} // Cierra main

/* Defectos del programa: En realidad el programa incluye varias partes,


las cuales no pueden ser tratadas de igual manera. Lo mas sencillo es revisar
si los parentesis (, [, { se cierran de manera adecuada. La manera de hacerlo
es un ejemplo tipico del poder de las pilas, este programa incluye partes de los
ejemplos que vienen en el libro de Bowman ( Algoritmos y Estructuras de D
atos.
Una Aproximacion en C) ademas la parte principal ( la funcion Revisa_Parentesis)
es una modificacion de la que se presenta en ese libro. El siguiente punto es
la revision de los comentarios. Para eso se introdujo la variable comentario,
que indica si se esta o no dentro de uno. Si se esta entonces no vale apilar
parentesis ni nada mas, lo unico importante es ver si en algun momento aparece
la condicion de cierre. Se ha utilizado solamente la forma de /* porque es la
tipica de el lenguaje C, sin embargo, deberia tambien incluirse el caso de //,
el cual es la forma de comentario en C++ pero que tambien es valido en C,
para este caso la condicion de
terminacion es '\n'. Este programa no considera el caso de las comillas ni los
apostrofos ni las secuencias de escape. Las secuencias de escape tienen validez
dentro de una cadena, esto, por lo menos en la forma en que se me ocurre,implica
crear una variable cadena a la que se le asigne ADENTRO o AFUERA. Sin embargo,
no es posible apilar las comillas porque en cualquier punto el programa no sabe
si esta es de apertura o de cierre, hay que atender ese problema con otra
variable. Si se esta dentro de una cadena, es necesario atender las entradas \
y ver que siga alguna secuencia de escape. El problema es mas o menos el mismo
para los apostrofos. En el caso de un compilador, este debe ademas indicar la
linea y el caracter en el que aparece el problema, ademas de decir exactamente
cual de todas las secuencias no se cerro de manera adecuada, para esto tambien
hay que introducir nuevas variables.....

Solo se me ocurre decir, con Kernighan y Ritchie: "Este programa es dificil si


se hace completamente general"
*/

También podría gustarte