CONJUNTO.YAC



/* OPERACIONES CON CONJUNTOS */
/* ==================================================*/
/* === Programa:    1.yac                         ===*/
/* === TEcnica:     Dirigida por la sintAxis      ===*/
/* === Programador: J. Rafael R. ochoa            ===*/
/* ==================================================*/

%{
   struct lista				// almacena el contenido de listas
   {
      char *dato;			// elemento de la lista
      struct lista *sig;		// apuntador al siguiente nodo
   };

   struct vars
   {
      char *nombre;
      struct lista *inicio;
      struct vars *sig;
   };

   struct vars *todo;			// todas las variables

%}

%union
{ 
   char str[80];
   struct lista *list;
}

%token PRINT UNION INTER COMA PLEFT PRIGHT IGUAL LINEA
%token CLEFT CRIGHT SALIR
%token <str> CAD
%type <list> items conjunto valor oper ciclo

%%
/* producciones de la gramatica */
lineas    : linea
	  | linea lineas
          | error LINEA {printf("\n:-) ");} lineas
	  ;
linea	  : asig LINEA                {printf("\n:-) ");}
          | PRINT oper LINEA          {muestra($2); printf("\n:-) ");}
          | SALIR                     {return;}
	  ;
oper      : valor                     {$$ = $1;}
          | valor UNION oper          {$$ = lista_une($1,$3);}
          | valor INTER oper          {$$ = interseccion($1,$3);}
          | ciclo UNION oper          {$$ = lista_une($1,$3);}
          | ciclo INTER oper          {$$ = interseccion($1,$3);}
          | ciclo                     {$$ = $1;}
          ;
ciclo     : PLEFT oper PRIGHT         {$$ = $2;}
          ;
asig      : CAD IGUAL oper              {asigna($1,$3);} 
          ;
valor	  : CAD                       {$$ = cont($1);}
          | conjunto		      {$$ = $1;}
	  ;
conjunto  : CLEFT items CRIGHT	      {$$ = $2;}
	  ;
items	  : CAD 		      {$$ = nodo($1);}
	  | CAD COMA items           {$$ = lista_une(nodo($1),$3);}
	  ;
%%

/* funciones auxiliares */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void muestra(struct lista *);
struct lista *nodo(char *);


extern int yylex();  /* Liga con la funcion yylex generada por LEX */
extern int yynerrs;

int yyparse();


void main(void)
{
   todo = NULL;
   printf("\n\n");
   printf("=========================================\n");
   printf("Las variables empiezan con v\n");
   printf("Por ejemplo vb=[1,2,3]\n");
   printf("terminar con \"salir\"\n");
   printf("===================================INICIO\n\n");
   printf(":-) ");
   yyparse();
   printf("\nok\n");
}

yyerror(char *mess)           /* llamado por yyparse() cuando ocurra */
{                             /*   un error                          */
  printf("\n [error...%s] \n",mess);
  return 1;
}

struct vars *existe_var(char *var)
{
   struct vars *variables = todo;
   while(variables)
   {
      if(strncmp(variables->nombre,var,strlen(var))==0)
         return variables;
      variables = variables->sig;
   }
   return NULL;
}

void asigna(char *var, struct lista *datos)
{
   struct vars *nodo = NULL;
   struct vars *aux = NULL;
   struct vars *ant = NULL;
   struct vars *ya_esta = NULL;

   if((ya_esta = existe_var(var)))
   {
      ya_esta->inicio = datos;
      muestra(nodo->inicio);
      return;
   }
   nodo = (struct vars *)malloc(sizeof(struct vars));

   nodo->nombre = strdup(var);
   nodo->inicio = datos;
   nodo->sig    = NULL;

   if (!todo) todo = nodo;
   else
   {
      aux = todo;
      while(aux)
      { ant = aux; aux=aux->sig; }
      ant->sig = nodo;
   }
   muestra(nodo->inicio);
}

struct lista *cont(char *var)
{
   struct vars *temp = NULL;

   temp = todo;
   while(temp)
   {
      if(strncmp(temp->nombre,var,strlen(var))==0) return temp->inicio;
      temp = temp->sig;
   }
   printf("No existe la variable %s\n",var);

   return NULL;
}

struct lista *copia(struct lista *list)
{
   struct lista *nueva = NULL;
   struct lista *nodo_new = NULL;
   struct lista *actual = NULL;

   if (!list) return NULL;
   while(list)
   {
      nodo_new = nodo(list->dato);
      if(!nueva) {nueva = nodo_new; actual = nodo_new;}
      else {actual->sig = nodo_new; actual = nodo_new;}
      list = list->sig;
   }
   return nueva;
}

struct lista *nodo(char *cad)
{
   struct lista *nodo_nuevo=NULL;

   nodo_nuevo = (struct lista *)malloc(sizeof(struct lista));
   nodo_nuevo->dato    = strdup(cad);
   nodo_nuevo->sig     = NULL;
   return nodo_nuevo;
}

int existe(char *nom, struct lista *contenido)
{
   while(contenido)
   {
      if (strncmp(contenido->dato,nom,strlen(nom))==0) return 1;
      contenido = contenido->sig;
   }
   return 0;
}



struct lista *interseccion(struct lista *cont1, struct lista *cont2)
{
   struct lista *salida = NULL;
   struct lista *nuevo  = NULL;
   struct lista *actual = NULL;

   if(!cont1 && !cont2) return NULL;
   if(!cont1) return NULL;
   if(!cont2) return NULL;

   while(cont1)
   {
      if (existe(cont1->dato,cont2))
      {
         nuevo = nodo(cont1->dato);
         if(!salida) {salida = nuevo; actual = nuevo;}
         else {actual->sig = nuevo; actual = nuevo;}
      }
      cont1 = cont1->sig;
   }
   return salida;
}

struct lista *lista_une(struct lista *l1, struct lista *l2)
{
   struct lista *salida = NULL;
   struct lista *ant    = NULL;
   struct lista *nuevo  = NULL;

   if(!l1 && !l2) return NULL;
   if(!l2) return l1;
   if(!l1) return l2;
   salida = copia(l2);
   while(l1)
   {
      if (!existe(l1->dato,salida))
      {
         nuevo = nodo(l1->dato);
         nuevo->sig = salida; salida     = nuevo;
      }
      l1 = l1->sig;
   }
   return salida;
}

void muestra(struct lista *ini)
{
   printf("\n");
   while(ini)
   {
      printf("%s ",ini->dato);
      ini = ini->sig;
   }
   printf("\n");
}