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 }
1.5.2