Página principal | Jerarquía de la clase | Lista alfabética | Lista de componentes | Lista de archivos | Miembros de las clases | Archivos de los miembros | Páginas relacionadas

regexp.C

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= regexp.cc                                             Diciembre de 1999 =
00003 //=-------------------------------------------------------------------------=
00004 //= Lector de expresiones regulares AQUYNZA                                 =
00005 //=-------------------------------------------------------------------------=
00006 //= ADVERTENCIA: ESTE SOFTWARE NO ESTA CONCEBIDO NI DISENNADO PARA EL USO   =
00007 //= EN EQUIPO DE CONTROL EN LINEA EN ENTORNOS PELIGROSOS QUE REQUIERAN UN   =
00008 //= DESEMPENNO LIBRE DE FALLAS, COMO LA OPERACION DE PLANTAS NUCLEARES,     = 
00009 //= SISTEMAS DE NAVEGACION O COMUNICACION EN AVIONES, TRAFICO AEREO,        =
00010 //= EQUIPO MEDICO DEL CUAL DEPENDAN VIDAS HUMANAS O SISTEMAS DE ARMAMENTO,  =
00011 //= EN LOS CUALES UNA FALLA EN EL SOFTWARE PUEDA IMPLICAR DIRECTAMENTE LA   =
00012 //= MUERTE, DANNOS PERSONALES O DANNOS FISICOS Y/O AMBIENTALES GRAVES       =
00013 //= ("ACTIVIDADES DE ALGO RIESGO").                                         =
00014 //=-------------------------------------------------------------------------=
00015 //= Autor original: Oscar J. Chavarro G.  A.K.A. JEDILINK. Copyright (c),   =
00016 //= 1997 - 2003, oscarchavarro@hotmail.com                                  =
00017 //= AQUYNZA es software libre, y se rige bajo los terminos de la licencia   =
00018 //= LGPL de GNU (http://www.gnu.org). Para mayor informacion respecto a la  =
00019 //= licencia de uso, consulte el archivo ./doc/LICENCIA en la distribucion. =
00020 //===========================================================================
00021 
00022 #include <ctype.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 
00027 #include "toolkits/util/regexp.h"
00028 #include "lista.cc"
00029 
00030 //===========================================================================
00031 //= CONSTANTES Y MACROS                                                     =
00032 //===========================================================================
00033 
00034 #define ES_OPERADOR(cad) \
00035     ( (cad)[0] == '+' || (cad)[0] == '-' || (cad)[0] == '*' || (cad)[0] == '/' || (cad)[0] == '^' )
00036 
00037 //===========================================================================
00038 //= Clase EXPRESION_REGULAR                                                 =
00039 //===========================================================================
00040 
00041 EXPRESION_REGULAR::EXPRESION_REGULAR()
00042 {
00043     Izq = NULL;
00044     Der = NULL;
00045     nombre_variable = NULL;
00046     tipo = OP_INVALIDO;
00047     valor = 0;
00048     ultimo_t = 0;
00049 }
00050 
00051 EXPRESION_REGULAR::~EXPRESION_REGULAR()
00052 {
00053     elim();
00054 }
00055 
00056 static double TMP_float;
00057 
00058 BOOLEAN
00059 EXPRESION_REGULAR::consultar_variable(const char *nombre_variable,
00060                        int &tipo, void **ref)
00063 {
00064     if ( strcmp(nombre_variable, "val") == 0 ) {
00065         TMP_float = evaluar(ultimo_t);
00066         tipo = T_FLOAT;
00067         (*ref) = &TMP_float;
00068         return TRUE;
00069     }
00070     return FALSE;
00071 }
00072 
00073 void
00074 EXPRESION_REGULAR::elim(void)
00075 {
00076     if ( Izq ) {
00077         delete Izq;
00078         Izq = NULL;
00079     }
00080     if ( Der ) {
00081         delete Der;
00082         Der = NULL;
00083     }
00084     if ( nombre_variable ) {
00085         delete nombre_variable;
00086         nombre_variable = NULL;
00087     }
00088     tipo = OP_INVALIDO;
00089     valor = 0;
00090 }
00091 
00092 int
00093 EXPRESION_REGULAR::clasificar_funcion(char *cad)
00094 {
00095     if ( strcmp(cad, "sin") == 0 ) {
00096         return FN_SIN;
00097     }
00098     else if ( strcmp(cad, "cos") == 0 ) {
00099         return FN_COS;
00100     }
00101     else if ( strcmp(cad, "log") == 0 ) {
00102         return FN_LOG;
00103     }
00104     return OP_INVALIDO;
00105 }
00106 
00107 BOOLEAN
00108 EXPRESION_REGULAR::leer(LISTA<char *> *Tokens)
00117 {
00118     //- Si soy una expresion encerrada en ()'s, los quito -------------------
00119     while ( strcmp((*Tokens)[0], "(") == 0 &&
00120             strcmp((*Tokens)[Tokens->tam() - 1], ")") == 0 ) {
00121         Tokens->elimElem(Tokens->tam()-1);
00122         Tokens->elimElem(0);
00123     }
00124 
00125     //- Caso trivial: Si soy alguito me creo... -----------------------------
00126     if ( Tokens->tam() == 1 ) {
00127         if ( ES_OPERADOR((*Tokens)[0]) ) {
00128             fprintf(stderr, "<EXPRESION_REGULAR> PARSE ERROR: "
00129                 "Operador \"%s\" mal parquiao'\n", (*Tokens)[0]);
00130             fflush(stderr);
00131             return FALSE;
00132         }
00133         if ( isdigit((*Tokens)[0][0]) ) {
00134             tipo = RA_CONSTANTE;
00135             valor = atof((*Tokens)[0]);
00136           }
00137           else {
00138             tipo = RA_VARIABLE;
00139             nombre_variable = new char[strlen((*Tokens)[0])]; 
00140             strcpy(nombre_variable, (*Tokens)[0]);
00141             if ( strcmp(nombre_variable, "PI") == 0 ) {
00142                 tipo = RA_CONSTANTE;
00143                 valor = PI;
00144                 return TRUE;
00145               }
00146               else if ( strcmp(nombre_variable, "t") != 0 ) {
00147                 fprintf(stderr,"<EXPRESION_REGULAR> ERROR:"
00148                  "Solo se acepta la variable \"t\" en esta version!\n");
00149                 fflush(stderr);
00150                 return FALSE;
00151             }
00152         }
00153         return TRUE;
00154     }
00155 
00156     //- Casos recursivos ----------------------------------------------------
00157     int i;
00158     int nivel = 0;
00159     LISTA <int> conectivos_principales;
00160     LISTA <char *> izq;
00161     LISTA <char *> der;
00162     int conectivo_principal = -1;
00163 
00164     // Busco conectivos de nivel 0
00165     for ( i = 0; i < Tokens->tam(); i++ ) {
00166         if ( (*Tokens)[i][0] == '(' ) nivel++;
00167         else if ( (*Tokens)[i][0] == ')' ) nivel--;
00168         if ( nivel == 0 && ES_OPERADOR((*Tokens)[i]) ) {
00169             conectivos_principales.anx(i);
00170         }
00171     }
00172 
00173     // Determino cual de los conectivos de nivel 0 es el principal
00174     if ( conectivos_principales.tam() > 0 ) {
00175         conectivo_principal = conectivos_principales[0];
00176       }
00177       else {
00178         tipo = clasificar_funcion((*Tokens)[0]);
00179         if ( tipo == OP_INVALIDO ) {
00180             fprintf(stderr,"<EXPRESION_REGULAR> ERROR: La "
00181               "funcion \"%s\" no se soporta!\n", (*Tokens)[0]);
00182             fflush(stderr);
00183             return FALSE;
00184         }
00185         Der = new EXPRESION_REGULAR();
00186         for ( i = 1; i < Tokens->tam(); i++ ) {
00187             der.anx((*Tokens)[i]);
00188         }
00189         return Der->leer(&der);
00190     }
00191     // '*' y '/' tienen prioridad sobre `^`
00192     for ( i = 0; i < conectivos_principales.tam(); i++ ) {
00193         if ( (*Tokens)[conectivos_principales[i]][0] == '*' || 
00194              (*Tokens)[conectivos_principales[i]][0] == '/' ) {
00195             conectivo_principal = conectivos_principales[i];
00196             break;
00197         }
00198     }
00199     // '+' y '-' tienen prioridad sobre los demas
00200     for ( i = 0; i < conectivos_principales.tam(); i++ ) {
00201         if ( (*Tokens)[conectivos_principales[i]][0] == '+' || 
00202              (*Tokens)[conectivos_principales[i]][0] == '-' ) {
00203             conectivo_principal = conectivos_principales[i];
00204             break;
00205         }
00206     }
00207 
00208     // Parta en dos la expresion
00209     int op = (*Tokens)[conectivo_principal][0];
00210 
00211     if ( op != '-' && conectivo_principal == 0 ) {
00212         fprintf(stderr, 
00213            "<EXPRESION_REGULAR> El operador \"%c\" no es unario.\n", op);
00214         fflush(stderr);
00215         return FALSE;
00216       }
00217       else if ( op == '-' && conectivo_principal == 0 ) {
00218         tipo = OP_NEGACION;
00219         Der = new EXPRESION_REGULAR();
00220         for ( i = 1; i < Tokens->tam(); i++ ) {
00221             der.anx((*Tokens)[i]);
00222         }
00223         if ( !Der->leer(&der) ) return FALSE; 
00224         else return TRUE;
00225       }
00226       else {
00227         for ( i = 0; i < conectivo_principal && i < Tokens->tam(); i++ ) {
00228             izq.anx((*Tokens)[i]);
00229         }
00230         for ( i = conectivo_principal + 1; i < Tokens->tam(); i++ ) {
00231             der.anx((*Tokens)[i]);
00232         }
00233     }
00234 
00235     switch ( op ) {
00236         case '+': tipo = OP_SUMA; break;
00237         case '-': tipo = OP_RESTA; break;
00238         case '*': tipo = OP_MULTIPLICACION; break;
00239         case '/': tipo = OP_DIVISION; break;
00240         case '^': tipo = OP_EXPONENTE; break;
00241         default: break;
00242     }
00243 
00244     Izq = new EXPRESION_REGULAR();
00245     Der = new EXPRESION_REGULAR();
00246 
00247     if ( !Izq->leer(&izq) || !Der->leer(&der) ) return FALSE; 
00248     return TRUE;
00249 }
00250 
00251 BOOLEAN
00252 EXPRESION_REGULAR::init(char *fuente)
00260 {
00261     elim();
00262 
00263     //-----------------------------------------------------------------------
00264     char *linea = new char[3 * strlen(fuente) + 1];
00265     int i, j;
00266     int nivel = 0;
00267 
00268     for ( i = 0, j = 0; i < fuente[i]; i++, j++ ) {
00269         if ( fuente[i] == '(' || fuente[i] == ')' || fuente[i] == '+' ||
00270              fuente[i] == '-' || fuente[i] == '*' || fuente[i] == '/' ||
00271              fuente[i] == '^' ) {
00272             linea[j] = ' ';  j++;
00273             linea[j] = fuente[i];  j++;
00274             linea[j] = ' ';   
00275           }
00276           else {
00277             linea[j] = fuente[i];
00278         }
00279         if ( fuente[i] == '(' ) nivel++;
00280         else if ( fuente[i] == ')' ) nivel--;
00281     }
00282     linea[j] = '\0';
00283 
00284     if ( nivel != 0 ) {
00285         fprintf(stderr,
00286             "<EXPRESION_REGULAR> PARSE ERROR: Parentesis des-balanceados!\n");
00287         fflush(stderr);
00288         delete linea;
00289         return FALSE;
00290     }
00291 
00292     //-----------------------------------------------------------------------
00293     char *ptr, *qtr;
00294     LISTA <char *> tokens;
00295 
00296     for ( ptr = strtok(linea, " \t\n"); ptr; ptr = strtok(NULL, " \t\n") ) {
00297         qtr = new char[strlen(ptr)+1];
00298         strcpy(qtr, ptr);
00299         tokens.anx(qtr);
00300     }
00301     delete linea;
00302 
00303     //-----------------------------------------------------------------------
00304     LISTA <char *> tokens_no_autonomos;
00305     BOOLEAN retorno;
00306 
00307     for ( i = 0; i < tokens.tam(); i++ ) {
00308         // Notese que estos no tienen memoria asignada!
00309         tokens_no_autonomos.anx(tokens[i]); 
00310     }
00311     retorno = leer(&tokens_no_autonomos);
00312 
00313     //-----------------------------------------------------------------------
00314     for ( i = 0; i < tokens.tam(); i++ ) {
00315         delete tokens[i];
00316     }
00317     tokens.elim();
00318 
00319     return retorno;
00320 }
00321 
00322 void
00323 EXPRESION_REGULAR::imprimir(void)
00324 {
00325     switch ( tipo ) {
00326       case RA_CONSTANTE:
00327         printf("%.2f", valor);
00328         break;
00329       case RA_VARIABLE:
00330         printf("%s", nombre_variable);
00331         break;
00332       case OP_NEGACION:
00333         printf("- (");
00334         Der->imprimir();
00335         printf(")");
00336         break;
00337       case OP_SUMA:
00338         printf("(");   Izq->imprimir();      printf(")");
00339         printf(" + ");
00340         printf("(");   Der->imprimir();      printf(")");
00341         break;
00342       case OP_RESTA:
00343         printf("(");   Izq->imprimir();      printf(")");
00344         printf(" - ");
00345         printf("(");   Der->imprimir();      printf(")");
00346         break;
00347       case OP_MULTIPLICACION:
00348         printf("(");   Izq->imprimir();      printf(")");
00349         printf(" * ");
00350         printf("(");   Der->imprimir();      printf(")");
00351         break;
00352       case OP_DIVISION:
00353         printf("(");   Izq->imprimir();      printf(")");
00354         printf(" / ");
00355         printf("(");   Der->imprimir();      printf(")");
00356         break;
00357       case OP_EXPONENTE:
00358         printf("(");   Izq->imprimir();      printf(")");
00359         printf(" ^ ");
00360         printf("(");   Der->imprimir();      printf(")");
00361         break;
00362       case FN_SIN:
00363         printf("sin(");   Der->imprimir();      printf(")");
00364         break;
00365       case FN_COS:
00366         printf("cos(");   Der->imprimir();      printf(")");
00367         break;
00368       case FN_LOG:
00369         printf("log(");   Der->imprimir();      printf(")");
00370         break;
00371       default: printf("{MA_ERROR}"); break;
00372     }
00373     fflush(stdout);
00374 }
00375 
00376 double
00377 EXPRESION_REGULAR::evaluar(double t)
00378 {
00379     ultimo_t = t;
00380     switch ( tipo ) {
00381       case RA_CONSTANTE:
00382         return valor;
00383       case RA_VARIABLE:  
00384         // OJO! Aqui debe mejorarse esto!
00385         return t;
00386       case OP_NEGACION:
00387         return Der->evaluar(t) * (-1);
00388       case OP_SUMA:
00389         return Izq->evaluar(t) + Der->evaluar(t);
00390       case OP_RESTA:
00391         return Izq->evaluar(t) - Der->evaluar(t);
00392       case OP_MULTIPLICACION:
00393         return Izq->evaluar(t) * Der->evaluar(t);
00394       case OP_DIVISION:
00395         return Izq->evaluar(t) / Der->evaluar(t);
00396       case OP_EXPONENTE:
00397         return pow(Izq->evaluar(t), Der->evaluar(t));
00398       case FN_SIN:
00399         return sin(Der->evaluar(t));
00400       case FN_COS:
00401         return cos(Der->evaluar(t));
00402       case FN_LOG:
00403         return log(Der->evaluar(t));
00404       default: break;
00405     }
00406     return 666;
00407 }
00408 
00409 //===========================================================================
00410 //= EOF                                                                     =
00411 //===========================================================================
00412 

Este archivo HTML ha sido generado automáticamente a partir del código fuente AQUYNZA. NO LO EDITE. Para mayor información contacte al autor.