/* 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; }