/* SIMPLIFICADOR DE EXPRESIONES MATEMATICAS */
/* ========================================================*/
/* === Programa: simplex.yac ===*/
/* === Objetivo: simplificar expresiones matemAticas ===*/
/* === TEcnica: Dirigida por la sintAxis ===*/
/* === Programador: J. Rafael R. Ochoa ===*/
/* ========================================================*/
%{
struct nodos
{
int valor;
char dato[80];
int exp;
struct nodos *sig;
};
%}
%union
{
struct nodos *lista;
char cadena[80];
}
%token LEFT RIGHT MAS POR LINEA CERO
%token <cadena> NUM VAR
%type <lista> expr term factor
%%
/* producciones de la gramatica */
inicio : expr LINEA { imprime($1); return 1;}
;
expr : expr MAS term { $$ = suma($1,$3); }
| term { $$ = $1; }
;
term : term POR factor { $$ = producto($1,$3); }
| factor { $$ = $1; }
;
factor : VAR { $$ = reserva($1); }
| NUM { $$ = reserva($1); }
| LEFT expr RIGHT { $$ = $2; }
;
%%
/* funciones auxiliares */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct nodos *reserva(char *);
void imprime(struct nodos *);
struct nodos *suma(struct nodos *, struct nodos *);
struct nodos *producto(struct nodos *, struct nodos *);
struct nodos *termino_que_falta(struct nodos *,struct nodos *);
struct nodos *copia_nodo(struct nodos *);
extern int yylex(); /* Liga con la funcion yylex generada por LEX */
extern int yynerrs;
int yyparse();
void main(void)
{
printf("\n=========================================\n");
yyparse();
printf("\n=========================================\n");
}
yyerror(char *mess) /* llamado por yyparse() cuando ocurra */
{ /* un error */
printf("\n [error...%s] \n",mess);
return 1;
}
struct nodos *suma(struct nodos *dato1, struct nodos *datos)
{
struct nodos *signo = NULL;
struct nodos *nuevo = NULL;
struct nodos *dato2 = NULL;
struct nodos *salida = NULL;
char sum[10];
int match;
salida = datos;
while(dato1)
{
dato2 = datos;
while(dato2)
{
match = 0;
if((strncmp(dato1->dato,dato2->dato,1)==0) &&
(dato1->exp==dato2->exp)
)
{
dato2->valor += dato1->valor;
match = 1; break;
}
dato2=dato2->sig;
}
if(!match)
{
signo = reserva("+");
nuevo = copia_nodo(dato1);
nuevo->sig = signo; signo->sig = datos;
datos = nuevo; salida = datos;
}
dato1=dato1->sig;
}
return salida;
}
struct nodos *copia_nodo(struct nodos *nodo)
{
struct nodos *copia = NULL;
copia = reserva(nodo->dato);
copia->valor = nodo->valor;
copia->exp = nodo->exp;
strcpy(copia->dato,nodo->dato);
return copia;
}
struct nodos *producto(struct nodos *dato1, struct nodos *dato2)
{
char prod[5]; struct nodos *nuevo=NULL;
struct nodos *termino2 = NULL;
if ((dato1->valor==0) || (dato2->valor==0)) return reserva("0");
sprintf(prod,"%d",dato1->valor*dato2->valor);
nuevo = reserva(prod);
if((strncmp(dato1->dato,"x",1)==0) && (strncmp(dato2->dato,"x",1)==0))
{ nuevo->exp = dato1->exp + dato2->exp;
strcpy(nuevo->dato,"x");
termino2 = termino_que_falta(dato1,dato2);
nuevo->sig = termino2;
return nuevo;
}
if((strncmp(dato1->dato,"x",1)==0) || (strncmp(dato2->dato,"x",1)==0))
{ strcpy(nuevo->dato,"x");
if(strncmp(dato1->dato,"x",1)==0) nuevo->exp = dato1->exp;
else nuevo->exp = dato2->exp;
termino2 = termino_que_falta(dato1,dato2);
nuevo->sig = termino2;
termino2 = termino_que_falta(dato1,dato2);
nuevo->sig = termino2;
return nuevo;
}
strcpy(nuevo->dato,"0");
return nuevo;
}
struct nodos *reserva(char *cad)
{
struct nodos *nodo_nuevo=NULL;
nodo_nuevo = (struct nodos *)malloc(sizeof(struct nodos));
if( strncmp(cad,"+",1)==0)
{ strcpy(nodo_nuevo->dato,"+"); nodo_nuevo->valor = 0; }
else if( strncmp(cad,"x",1)==0)
{ strcpy(nodo_nuevo->dato,"x"); nodo_nuevo->valor = 1; }
else
{ strcpy(nodo_nuevo->dato,"0"); nodo_nuevo->valor = atoi(cad); }
nodo_nuevo->exp = 1;
nodo_nuevo->sig = NULL;
return nodo_nuevo;
}
void imprime(struct nodos *lista)
{
while(lista)
{
if(strncmp(lista->dato,"0",1)==0)
{
if (lista->valor !=0) printf("%d",lista->valor);
}
if(strncmp(lista->dato,"+",1)==0)
{
if(lista->sig->valor !=0) printf("+");
}
if(strncmp(lista->dato,"x",1)==0)
{
if(lista->valor != 1) printf("%d",lista->valor);
printf("x");
if(lista->exp != 1) printf("^%d",lista->exp);
}
lista = lista->sig;
}
}
struct nodos *termino_que_falta(struct nodos *dato1,struct nodos *dato2)
{
struct nodos *nuevo = NULL;
char num[10];
if(!dato1->sig && !dato2->sig) return NULL;
if(!dato1->sig)
{
sprintf(num,"%d",dato1->valor*dato2->sig->valor);
nuevo = reserva(num);
if((strncmp(dato1->dato,"x",1)==0) ||
(strncmp(dato2->sig->dato,"x",1)==0))
strcpy(nuevo->dato,"x");
}
else
{
sprintf(num,"%d",dato2->valor*dato1->sig->valor);
nuevo = reserva(num);
if((strncmp(dato1->dato,"x",1)==0) ||
(strncmp(dato2->sig->dato,"x",1)==0))
strcpy(nuevo->dato,"x");
}
return nuevo;
}