expr.cc00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "expr.h"
00023
00024 Expression::~Expression()
00025 {
00026 }
00027
00028 Value Expression::evaluate ()
00029 {
00030 return eval ();
00031 }
00032
00033
00034 Value UnaryExpression::eval ()
00035 {
00036 Value v = expr_->evaluate ();
00037
00038 if (type_ == T_MINUS)
00039 return -v;
00040 else if (type_ == T_NOT)
00041 return ~v;
00042 else
00043 return v;
00044 }
00045
00046
00047 Value BinaryExpression::eval ()
00048 {
00049 Value l = left_->evaluate ();
00050 Value r = right_->evaluate ();
00051
00052 switch (type_)
00053 {
00054 case T_PLUS:
00055 return l + r;
00056 case T_MINUS:
00057 return l - r;
00058 case T_MUL:
00059 return l * r;
00060 case T_DIV:
00061 return l / r;
00062 case T_AND:
00063 return l & r;
00064 case T_OR:
00065 return l | r;
00066 case T_XOR:
00067 return l ^ r;
00068 default:
00069 return l;
00070 }
00071 }
00072
00073
00074 Value ValueExpression::eval ()
00075 {
00076 return value_;
00077 }
00078
00079 Value Expression::eval()
00080 {
00081 return 0;
00082 }
00083
00084 void Expression::rewind (enum token t, const char*& line)
00085 {
00086 if (t == T_EOF)
00087 return;
00088 line--;
00089 }
00090
00091 enum Expression::token Expression::get_token(const char*& line)
00092 {
00093 char c;
00094
00095 do {
00096 c = *line++;
00097 } while (c == ' ' || c == '\t');
00098
00099 switch (c)
00100 {
00101 case 0:
00102 line--;
00103 return T_EOF;
00104 case '-':
00105 return T_MINUS;
00106 case '+':
00107 return T_PLUS;
00108 case '*':
00109 return T_MUL;
00110 case '/':
00111 return T_DIV;
00112 case '|':
00113 return T_OR;
00114 case '&':
00115 return T_AND;
00116 case '^':
00117 return T_XOR;
00118 case '~':
00119 return T_NOT;
00120 case '(':
00121 return T_PARENT_OPEN;
00122 case ')':
00123 return T_PARENT_CLOSE;
00124 default:
00125 if (c >= '0' && c <= '9')
00126 return T_DIGIT;
00127 if (c >= 'a' && c <= 'z')
00128 return T_NAME;
00129 if (c >= 'A' && c <= 'Z')
00130 return T_NAME;
00131 return T_UNKNOWN;
00132 }
00133 }
00134
00135
00136 unsigned char Expression::get_priority(enum token t)
00137 {
00138 switch (t)
00139 {
00140 case T_MINUS:
00141 case T_PLUS:
00142 return 2;
00143
00144 case T_AND:
00145 case T_OR:
00146 case T_XOR:
00147 return 1;
00148
00149 case T_MUL:
00150 case T_DIV:
00151 return 3;
00152
00153 case T_NOT:
00154 return 4;
00155
00156 default:
00157 return 5;
00158 }
00159 }
00160
00161
00162 Expression* Expression::parse_unary(const char*& line)
00163 {
00164 enum token t = get_token (line);
00165 if (t == T_MINUS || t == T_NOT)
00166 {
00167 Expression* e = parse_binary (line, 0);
00168 if (e)
00169 e = new UnaryExpression (t, e);
00170 return e;
00171 }
00172 else
00173 {
00174 rewind (t, line);
00175 return parse_binary (line, 0);
00176 }
00177 }
00178
00179
00180 Expression* Expression::parse_binary(const char*& line, unsigned char prio)
00181 {
00182 Expression* current = parse_term (line);
00183 if (current == 0)
00184 return 0;
00185
00186 while (1)
00187 {
00188 enum token t = get_token (line);
00189 if (t != T_MINUS && t != T_PLUS
00190 && t != T_MUL && t != T_DIV
00191 && t != T_AND && t != T_OR && t != T_XOR)
00192 {
00193 rewind (t, line);
00194 return current;
00195 }
00196
00197 unsigned char p = Expression::get_priority (t);
00198 if (p < prio)
00199 {
00200 rewind (t, line);
00201 return current;
00202 }
00203 Expression* r;
00204 if (p > prio)
00205 r = parse_binary (line, p + 1);
00206 else
00207 r = parse_term (line);
00208
00209 if (r == 0)
00210 {
00211 delete current;
00212 return 0;
00213 }
00214 current = new BinaryExpression (t, current, r);
00215 }
00216 }
00217
00218
00219
00220
00221
00222
00223 int
00224 Expression::get_value(const char*& buf, Value& v)
00225 {
00226 long value = 0;
00227 char c;
00228
00229 if (!(*buf >= '0' && *buf <= '9'))
00230 return -1;
00231
00232
00233 if (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X'))
00234 {
00235 buf += 2;
00236 while ((c = *buf++))
00237 {
00238 if (c >= '0' && c <= '9')
00239 c = c - '0';
00240 else if (c >= 'a' && c <= 'f')
00241 c = c - 'a' + 10;
00242 else if (c >= 'A' && c <= 'F')
00243 c = c - 'A' + 10;
00244 else if (c >= 'a' && c <= 'z')
00245 return -1;
00246 else if (c >= 'A' && c <= 'Z')
00247 return -1;
00248 else
00249 {
00250 buf--;
00251 break;
00252 }
00253
00254 value = (value << 4) | (long) ((unsigned) c);
00255 }
00256 v = value;
00257 return 0;
00258 }
00259 else
00260 {
00261 int sign = 0;
00262
00263 if (buf[0] == '-')
00264 {
00265 sign = 1;
00266 buf++;
00267 }
00268 while ((c = *buf++) != 0)
00269 {
00270 if (c >= '0' && c <= '9')
00271 c = c - '0';
00272 else if (c >= 'a' && c <= 'Z')
00273 return -1;
00274 else if (c >= 'A' && c <= 'Z')
00275 return -1;
00276 else
00277 {
00278 buf--;
00279 break;
00280 }
00281 value = (value * 10) + (long) c;
00282 }
00283 if (sign)
00284 value = -value;
00285 v = value;
00286 return 0;
00287 }
00288 return -1;
00289 }
00290
00291
00292 Expression* Expression::parse_term(const char*& line)
00293 {
00294 enum token t = get_token (line);
00295 if (t == T_PARENT_OPEN)
00296 {
00297 Expression* e = parse_unary (line);
00298 if (e == 0)
00299 return 0;
00300
00301 t = get_token (line);
00302 if (t == T_PARENT_CLOSE)
00303 return e;
00304
00305 rewind (t, line);
00306 delete e;
00307 return 0;
00308 }
00309 if (t == T_DIGIT)
00310 {
00311 rewind (t, line);
00312 Value val;
00313 if (get_value (line, val) != 0)
00314 return 0;
00315
00316 Expression* e = new ValueExpression (val);
00317 return e;
00318 }
00319 return 0;
00320 }
00321
00322 Expression* Expression::parse(const char*& line)
00323 {
00324 return parse_unary (line);
00325 }
00326
|