lib/intExp.c

Go to the documentation of this file.
00001 /* Below is the worlds sleaziest little numerical expression
00002  * evaluator. Used to do only ints, now does doubles as well. 
00003  *
00004  * This file is copyright 2002 Jim Kent, but license is hereby
00005  * granted for all use - public, private or commercial. */
00006 
00007 #include "common.h"
00008 #include "kxTok.h"
00009 
00010 static char const rcsid[] = "$Id: intExp.c,v 1.6 2003/05/06 07:33:43 kate Exp $";
00011 
00012 static struct kxTok *tok;
00013 
00014 #define nextTok() (tok = tok->next) 
00015 
00016 #ifdef DEBUG
00017 static void nextTok()
00018 /* Advance to next token. */
00019 {
00020 if (tok == NULL)
00021     printf("(null)");
00022 else
00023     {
00024     printf("'%s' -> ", tok->string);
00025     if (tok->next == NULL)
00026         printf("(null)\n");
00027     else
00028         printf("'%s'\n", tok->next->string);
00029     }
00030 tok = tok->next;
00031 }
00032 #endif /* DEBUG */
00033 
00034 
00035 static double expression();
00036 /* Forward declaration of main expression handler. */
00037 
00038 static double number()
00039 /* Return number. */
00040 {
00041 double val;
00042 if (tok == NULL)
00043     errAbort("Parse error in numerical expression");
00044 if (!isdigit(tok->string[0]))
00045     errAbort("Expecting number, got %s", tok->string);
00046 val = atof(tok->string);
00047 nextTok();
00048 return val;
00049 }
00050 
00051 static double atom()
00052 /* Return parenthetical expression or number. */
00053 {
00054 double val;
00055 if (tok->type == kxtOpenParen)
00056     {
00057     nextTok();
00058     val = expression();
00059     if (tok->type == kxtCloseParen)
00060         {
00061         nextTok();
00062         return val;
00063         }
00064     else
00065         {
00066         errAbort("Unmatched parenthesis");
00067         return 0;
00068         }
00069     }
00070 else
00071     return number();
00072 }
00073 
00074 
00075 static double uMinus()
00076 /* Unary minus. */
00077 {
00078 double val;
00079 if (tok->type == kxtSub)
00080     {
00081     nextTok();
00082     val = -atom();
00083     return val;
00084     }
00085 else
00086     return atom();
00087 }
00088 
00089 static double mulDiv()
00090 /* Multiplication or division. */
00091 {
00092 double val = uMinus();
00093 for (;;)
00094     {
00095     if (tok->type == kxtMul)
00096         {
00097         nextTok();
00098         val *= uMinus();
00099         }
00100     else if (tok->type == kxtDiv)
00101         {
00102         nextTok();
00103         val /= uMinus();
00104         }
00105     else
00106         break;
00107     }
00108 return val;
00109 }
00110 
00111 static double addSub()
00112 /* Addition or subtraction. */
00113 {
00114 double val;
00115 val = mulDiv();
00116 for (;;)
00117     {
00118     if (tok->type == kxtAdd)
00119         {
00120         nextTok();
00121         val += mulDiv();
00122         }
00123     else if (tok->type == kxtSub)
00124         {
00125         nextTok();
00126         val -= mulDiv();
00127         }
00128     else
00129         break;
00130     }
00131 return val;
00132 }
00133 
00134 static double expression()
00135 /* Wraps around lowest level of expression. */
00136 {
00137 return addSub();
00138 }
00139 
00140 double doubleExp(char *text)
00141 /* Convert text to double expression and evaluate. */
00142 {
00143 double val;
00144 struct kxTok *tokList = tok = kxTokenize(text, FALSE);
00145 val = expression();
00146 slFreeList(&tokList);
00147 return val;
00148 }
00149 
00150 int intExp(char *text)
00151 /* Convert text to int expression and evaluate. */
00152 {
00153 return round(doubleExp(text));
00154 }

Generated on Tue Dec 25 18:39:31 2007 for blat by  doxygen 1.5.2