00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <math.h>
00027
00028 #include "AtomParser.h"
00029 #include "y.tab.h"
00030 #include "ParseTree.h"
00031 #include "Inform.h"
00032 #include "JRegex.h"
00033 #include "AtomSel.h"
00034 #include "Timestep.h"
00035 #include "DrawMolecule.h"
00036 #include "SpatialSearch.h"
00037
00038
00039 #define case_compare_numeric_macro(switchcase, symbol) \
00040 case switchcase: \
00041 l->convert(SymbolTableElement::IS_FLOAT); \
00042 r->convert(SymbolTableElement::IS_FLOAT); \
00043 ldval = l->dval; \
00044 rdval = r->dval; \
00045 flg = flgs; \
00046 for (i=num-1; i>=0; i--) { \
00047 *flg &= (*ldval symbol *rdval); \
00048 ldval += lincr; rdval += rincr; flg++; \
00049 } \
00050 break;
00051
00052 #define case_compare_string_macro(switchcase, symbol) \
00053 case switchcase: \
00054 l->convert(SymbolTableElement::IS_STRING); \
00055 r->convert(SymbolTableElement::IS_STRING); \
00056 lsptr = l->sval; \
00057 rsptr = r->sval; \
00058 flg = flgs; \
00059 for (i=num-1; i>=0; i--) { \
00060 if (*flg) \
00061 *flg &= (strcmp(*lsptr, *rsptr) symbol 0); \
00062 lsptr += lincr; rsptr += rincr; flg++; \
00063 } \
00064 break;
00065
00066
00068 ParseTree::ParseTree(SymbolTable *parser, atomparser_node *parse_tree)
00069 {
00070 tree = parse_tree;
00071 table = parser;
00072 selected_array = NULL;
00073 num_selected = 0;
00074 context = NULL;
00075 }
00076
00077 ParseTree::~ParseTree(void) {
00078 if (selected_array != NULL)
00079 delete [] selected_array;
00080 delete tree;
00081 }
00082
00083 void ParseTree::eval_compare(atomparser_node *node, int num, int *flgs) {
00084 int i;
00085 double *ldval, *rdval;
00086 char **lsptr, **rsptr;
00087 int lincr, rincr;
00088 int *flg;
00089
00090
00091 symbol_data *l = eval(node->left, num, flgs);
00092 symbol_data *r = eval(node->right, num, flgs);
00093
00094
00095
00096
00097 lincr = l->num == num ? 1 : 0;
00098 rincr = r->num == num ? 1 : 0;
00099
00100 switch (node->ival) {
00101 case_compare_numeric_macro(NLT, < )
00102 case_compare_numeric_macro(NLE, <= )
00103 case_compare_numeric_macro(NEQ, == )
00104 case_compare_numeric_macro(NGE, >= )
00105 case_compare_numeric_macro(NGT, > )
00106 case_compare_numeric_macro(NNE, != )
00107
00108 case_compare_string_macro(SLT, < )
00109 case_compare_string_macro(SLE, <= )
00110 case_compare_string_macro(SEQ, == )
00111 case_compare_string_macro(SGE, >= )
00112 case_compare_string_macro(SGT, > )
00113 case_compare_string_macro(SNE, != )
00114
00115 case MATCH: {
00116 l->convert(SymbolTableElement::IS_STRING);
00117 r->convert(SymbolTableElement::IS_STRING);
00118 lsptr = l->sval;
00119 rsptr = r->sval;
00120 flg = flgs;
00121 JRegex *rgx = NULL;
00122 const char *first = *rsptr;
00123
00124 for (i=0; i<num; i++) {
00125 if (i==0 || strcmp(*rsptr, first)) {
00126 if (rgx)
00127 delete rgx;
00128 rgx = new JRegex(*rsptr);
00129 first = *rsptr;
00130 }
00131 if (rgx) {
00132 if (*flg)
00133 *flg &= (rgx->match(*lsptr, strlen(*lsptr)) != -1);
00134 } else {
00135 *flg = 0;
00136 }
00137 lsptr += lincr; rsptr += rincr; flg++;
00138 }
00139 if (rgx) {
00140 delete rgx;
00141 }
00142
00143 break;
00144 }
00145
00146 default:
00147 msgWarn << "ParseTree::eval_compare() missing operator!" << sendmsg;
00148 }
00149
00150 delete l;
00151 delete r;
00152 }
00153
00154
00155
00156 symbol_data * ParseTree::eval_mathop(atomparser_node *node, int num, int *flgs)
00157 {
00158 symbol_data *l = eval(node->left, num, flgs);
00159 symbol_data *r = eval(node->right, num, flgs);
00160
00161
00162
00163 int lincr = l->num == num ? (~0) : 0;
00164 int rincr = r->num == num ? (~0) : 0;
00165 l->convert(SymbolTableElement::IS_FLOAT);
00166 r->convert(SymbolTableElement::IS_FLOAT);
00167 symbol_data *tmp = new symbol_data(SymbolTableElement::IS_FLOAT, num);
00168 int i;
00169 const double *lval = l->dval;
00170 const double *rval = r->dval;
00171 double *tmpval = tmp->dval;
00172
00173
00174
00175
00176
00177
00178 switch (node->node_type) {
00179 case ADD:
00180 for (i=num-1; i>=0; i--) {
00181 if (flgs[i]) tmpval[i] = lval[lincr & i] + rval[rincr & i];
00182 }
00183 break;
00184 case SUB:
00185 for (i=num-1; i>=0; i--) {
00186 if (flgs[i]) tmpval[i] = lval[lincr & i] - rval[rincr & i];
00187 }
00188 break;
00189 case MULT:
00190 for (i=num-1; i>=0; i--) {
00191 if (flgs[i]) tmpval[i] = lval[lincr & i] * rval[rincr & i];
00192 }
00193 break;
00194 case DIV:
00195 for (i=num-1; i>=0; i--) {
00196 if (flgs[i]) tmpval[i] = lval[lincr & i] / rval[rincr & i];
00197 }
00198 break;
00199 case MOD:
00200 for (i=num-1; i>=0; i--) {
00201 if (flgs[i]) tmpval[i] = fmod(lval[lincr & i], rval[rincr & i]);
00202 }
00203 break;
00204 case EXP:
00205 for (i=num-1; i>=0; i--) {
00206 if (flgs[i]) tmpval[i] = pow(lval[lincr & i], rval[rincr & i]);
00207 }
00208 break;
00209 }
00210
00211 delete l;
00212 delete r;
00213 return tmp;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 void ParseTree::eval_stringfctn(atomparser_node *node, int num, int *flgs) {
00226 int count = 0;
00227 atomparser_node *left;
00228
00229
00230 for (left = node->left; left != NULL; left = left->left) {
00231 count++;
00232 }
00233 if (count == 0)
00234 return;
00235
00236
00237 char **argv= (char **) calloc(1, count * sizeof(char *));
00238 int *types = new int[count];
00239 int i=0;
00240 for (left = node->left; left != NULL; left = left -> left, i++) {
00241
00242 switch (left->sele.st) {
00243 case RAW_STRING:
00244 types[i] = 0;
00245 argv[i] = (char *) ((const char *) left->sele.s);
00246 break;
00247
00248 case SQ_STRING:
00249 types[i] = 1;
00250 argv[i] = (char *) ((const char *) left->sele.s);
00251 break;
00252
00253 case DQ_STRING:
00254 types[i] = 2;
00255 argv[i] = (char *) ((const char *) left->sele.s);
00256 break;
00257 }
00258
00259 if (left->extra_type != -1) {
00260 types[i] += 3;
00261 }
00262 }
00263
00264
00265 int *tmp_flgs = new int[num];
00266 memcpy(tmp_flgs, flgs, num * sizeof(int));
00267 SymbolTableElement *elem = table->fctns.data(node->extra_type);
00268 elem->keyword_stringfctn(context, count, (const char **)argv, types, num, tmp_flgs);
00269
00270 for (i = num-1; i>=0; i--) {
00271 if (flgs[i]) flgs[i] = tmp_flgs[i];
00272 }
00273 delete [] tmp_flgs;
00274 delete [] types;
00275 free(argv);
00276 }
00277
00278 static void same_string(symbol_data *tmp, symbol_data *tmp2, int num,
00279 int *subselect, int *flgs) {
00280 hash_t hash;
00281 int i;
00282 hash_init(&hash, num);
00283
00284
00285 for (i=0; i<num; i++)
00286 if (subselect[i])
00287 hash_insert(&hash, tmp2->sval[i], 0);
00288
00289
00290
00291
00292 for (i=0; i<num; i++)
00293 if (flgs[i])
00294 flgs[i] = (hash_lookup(&hash, tmp->sval[i]) != HASH_FAIL);
00295
00296 hash_destroy(&hash);
00297 }
00298
00299 static void same_int(symbol_data *tmp, symbol_data *tmp2, int num,
00300 int *subselect, int *flgs) {
00301
00302
00303 int *int_table = NULL, int_min, int_max;
00304 int i;
00305 for (i=0; i<num; i++) if (subselect[i]) break;
00306 if (i==num) {
00307
00308 memset(flgs, 0, num*sizeof(int));
00309 return;
00310 }
00311 int_min = int_max = tmp2->ival[i];
00312 while (++i < num) {
00313 if (!subselect[i]) continue;
00314 int ival = tmp2->ival[i];
00315 if (ival > int_max)
00316 int_max = ival;
00317 if (ival < int_min)
00318 int_min = ival;
00319 }
00320 int_table = (int *) calloc(1+int_max-int_min,sizeof(int));
00321 for (i=0; i<num; i++) {
00322 if (subselect[i]) {
00323 int_table[tmp2->ival[i]-int_min] = 1;
00324 }
00325 }
00326
00327
00328 for (i=0; i<num; i++) {
00329 if (flgs[i]) {
00330 int ival = tmp->ival[i];
00331 if (ival >= int_min && ival <= int_max)
00332 flgs[i] = int_table[ival-int_min];
00333 else
00334 flgs[i] = 0;
00335 }
00336 }
00337 delete [] int_table;
00338 }
00339
00340 static void same_double(symbol_data *tmp, symbol_data *tmp2, int num,
00341 int *subselect, int *flgs) {
00342
00343
00344 hash_t hash;
00345 int i, n=0;
00346 for (i=0; i<num; i++) n += subselect[i];
00347 char *doublestring = new char[25*n];
00348 char *istring = doublestring;
00349 hash_init(&hash, n);
00350 for (i=0; i<num; i++)
00351 if (subselect[i]) {
00352 sprintf(istring,"%f", (double) tmp2->dval[i]);
00353 hash_insert(&hash, istring, 0);
00354 istring += 25;
00355 }
00356 char tmpstring[25];
00357 for (i=0; i<num; i++) {
00358 sprintf(tmpstring,"%f", (double) tmp->dval[i]);
00359 flgs[i] &= (hash_lookup(&hash, tmpstring) != HASH_FAIL);
00360 }
00361 hash_destroy(&hash);
00362 delete [] doublestring;
00363 }
00364
00365
00366
00367
00368
00369
00370 void ParseTree::eval_same( atomparser_node *node, int num, int *flgs) {
00371 int i;
00372 int *subselect = new int[num];
00373 for (i=0; i<num; subselect[i++]=1);
00374
00375
00376 if (eval(node->left, num, subselect)) {
00377 delete [] subselect;
00378 msgErr << "eval of a 'same' returned data when it shouldn't have"
00379 << sendmsg;
00380 return;
00381 }
00382
00383
00384
00385
00386 SymbolTableElement *elem = table->fctns.data(node->extra_type);
00387 SymbolTableElement::symtype has_type = elem->returns_a;
00388 symbol_data *tmp, *tmp2;
00389 tmp = new symbol_data(has_type, num);
00390 tmp2 = new symbol_data(has_type, num);
00391
00392
00393
00394 switch (has_type) {
00395 case SymbolTableElement::IS_INT:
00396 elem->keyword_int(context, num, tmp->ival, flgs);
00397 elem->keyword_int(context, num, tmp2->ival, subselect);
00398 same_int(tmp, tmp2, num, subselect, flgs);
00399 break;
00400
00401 case SymbolTableElement::IS_FLOAT:
00402 elem->keyword_double(context, num, tmp->dval, flgs);
00403 elem->keyword_double(context, num, tmp2->dval, subselect);
00404 same_double(tmp, tmp2, num, subselect, flgs);
00405 break;
00406
00407 case SymbolTableElement::IS_STRING:
00408 elem->keyword_string(context, num, (const char **)tmp->sval, flgs);
00409 elem->keyword_string(context, num, (const char **)tmp2->sval, subselect);
00410 same_string(tmp, tmp2, num, subselect, flgs);
00411 break;
00412 }
00413
00414 delete tmp;
00415 delete tmp2;
00416 delete [] subselect;
00417 }
00418
00419
00420
00421
00422 symbol_data *ParseTree::eval_key( atomparser_node *node, int num, int *flgs) {
00423
00424 SymbolTableElement *elem = table->fctns.data(node->extra_type);
00425 SymbolTableElement::symtype has_type = elem->returns_a;
00426 symbol_data *tmp;
00427 tmp = new symbol_data(has_type, num);
00428
00429 switch (has_type) {
00430 case SymbolTableElement::IS_INT:
00431 elem->keyword_int(context, num, tmp->ival, flgs);
00432 break;
00433 case SymbolTableElement::IS_FLOAT:
00434 elem->keyword_double(context, num, tmp->dval, flgs);
00435 break;
00436 case SymbolTableElement::IS_STRING:
00437 elem->keyword_string(context, num, (const char **)tmp->sval, flgs);
00438 break;
00439 }
00440
00441
00442
00443 int *int_table = NULL;
00444
00445 int int_min=0, int_max=0;
00446 int have_first=0;
00447 if (has_type == SymbolTableElement::IS_INT) {
00448 for (int i=0; i<num; i++) {
00449 if (!flgs[i])
00450 continue;
00451
00452 if (!have_first) {
00453 int_min = int_max = tmp->ival[i];
00454 have_first = 1;
00455 } else {
00456 const int ival = tmp->ival[i];
00457 if (ival > int_max)
00458 int_max = ival;
00459 if (ival < int_min)
00460 int_min = ival;
00461 }
00462 }
00463 int_table = (int *) calloc(1+int_max-int_min, sizeof(int));
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473 int *newflgs = new int[num];
00474 for (int i=num-1; i>=0; i--) {
00475 newflgs[i] = 0;
00476 }
00477
00478 if (node->left) {
00479 atomparser_node *left = node->left;
00480 while (left) {
00481 if (left->extra_type == -1) {
00482
00483 switch(has_type) {
00484 case SymbolTableElement::IS_INT:
00485 {
00486 int ival = atoi(left->sele.s);
00487 if (ival >= int_min && ival <= int_max)
00488 int_table[ival-int_min] = 1;
00489 }
00490 break;
00491
00492 case SymbolTableElement::IS_FLOAT:
00493 {
00494
00495 double dval = atof(left->sele.s);
00496 double delta = fabs(dval / 1000);
00497 double maxval = dval+delta;
00498 double minval = dval-delta;
00499 for (int i=num-1; i>=0; i--) {
00500 if (flgs[i])
00501 newflgs[i] |= (minval <= tmp->dval[i] && maxval >= tmp->dval[i]);
00502 }
00503 }
00504 break;
00505
00506 case SymbolTableElement::IS_STRING:
00507 {
00508 switch (left->sele.st) {
00509 case SQ_STRING:
00510 case RAW_STRING:
00511 {
00512 for (int i=num-1; i>=0; i--) {
00513
00514
00515
00516 if (flgs[i] && (tmp->sval[i] != NULL)) {
00517 newflgs[i] |= !strcmp(left->sele.s, tmp->sval[i]);
00518 }
00519 }
00520 }
00521 break;
00522
00523 case DQ_STRING:
00524 default:
00525 {
00526
00527
00528
00529
00530
00531
00532 JString temps = "^("+left->sele.s+")$";
00533 JRegex r(temps, 1);
00534 for (int i=num-1; i>=0; i--) {
00535 if (flgs[i]) newflgs[i] |= (r.match(tmp->sval[i],
00536 strlen(tmp->sval[i])) != -1);
00537 }
00538 }
00539 break;
00540 }
00541 }
00542 }
00543 } else {
00544 switch(has_type) {
00545 case SymbolTableElement::IS_INT:
00546 {
00547 int ltval = atoi(left->sele.s);
00548 int gtval = atoi(left->left->sele.s);
00549 if (ltval < int_min) ltval = int_min;
00550 if (gtval > int_max) gtval = int_max;
00551 for (int i=ltval-int_min; i<= gtval-int_min; i++)
00552 int_table[i] = 1;
00553 }
00554 break;
00555 case SymbolTableElement::IS_FLOAT:
00556 {
00557 double ltval = atof(left->sele.s);
00558 double gtval = atof(left->left->sele.s);
00559 for (int i=num-1; i>=0; i--) {
00560 if (flgs[i])
00561 newflgs[i] |= ((ltval <= tmp->dval[i]) && (gtval >= tmp->dval[i]));
00562 }
00563 }
00564 break;
00565 default:
00566 {
00567
00568 for (int i=num-1; i>=0; i--) {
00569 if (flgs[i])
00570 newflgs[i] |= (flgs[i] && strcmp(left->sele.s, tmp->sval[i]) <= 0
00571 && strcmp(left->left->sele.s, tmp->sval[i]) >= 0);
00572
00573 }
00574 }
00575 }
00576 left = left->left;
00577 }
00578 left = left->left;
00579 }
00580
00581
00582 if (has_type == SymbolTableElement::IS_INT) {
00583 for (int i=0; i<num; i++) {
00584 if (flgs[i])
00585 flgs[i] = int_table[tmp->ival[i]-int_min];
00586 }
00587 free(int_table);
00588 } else {
00589 for (int i=num-1; i>=0; i--) {
00590 if (flgs[i])
00591 flgs[i] = newflgs[i];
00592 }
00593 }
00594 delete [] newflgs;
00595 delete tmp;
00596 return NULL;
00597 } else {
00598
00599
00600
00601 delete [] newflgs;
00602 return tmp;
00603 }
00604 }
00605
00606
00607 void ParseTree::eval_single(atomparser_node *node, int num, int *flgs) {
00608
00609
00610 atomsel_ctxt *ctxt = (atomsel_ctxt *)context;
00611 ctxt->singleword = table->fctns.name(node->extra_type);
00612 table->fctns.data(node->extra_type)->keyword_single(context, num, flgs);
00613 }
00614
00615
00616 void ParseTree::eval_exwithin(atomparser_node *node, int num, int *flgs) {
00617 eval_within(node, num, flgs);
00618
00619
00620 int *others = new int[num];
00621 int i;
00622 for (i=0; i<num; others[i++] = 1);
00623
00624
00625 if (eval(node->left, num, others)) {
00626 delete [] others;
00627 msgErr << "eval of a 'within' returned data when it shouldn't have." << sendmsg;
00628 return;
00629 }
00630 for (i=0; i<num; i++) {
00631 if (others[i]) flgs[i] = 0;
00632 }
00633 delete [] others;
00634 }
00635
00636
00637
00638 static Timestep *selframe(DrawMolecule *atom_sel_mol, int which_frame) {
00639 switch (which_frame) {
00640 case AtomSel::TS_LAST: return atom_sel_mol->get_last_frame();
00641 case AtomSel::TS_NOW : return atom_sel_mol->current();
00642 default: {
00643 if (!atom_sel_mol->get_frame(which_frame)) {
00644 return atom_sel_mol->get_last_frame();
00645
00646 } else {
00647 return atom_sel_mol->get_frame(which_frame);
00648 }
00649 }
00650 }
00651 return NULL;
00652 }
00653
00654 void ParseTree::eval_pbwithin(atomparser_node *node, int num, int *flgs) {
00655
00656 int i;
00657
00658 ResizeArray<float> coords(3*2*num);
00659
00660
00661
00662 ResizeArray<int> others(2*num);
00663
00664
00665
00666
00667 ResizeArray<int> repflgs(2*num);
00668
00669
00670 ResizeArray<int> repindexes(num);
00671
00672
00673 atomsel_ctxt *ctxt = (atomsel_ctxt *)context;
00674 const Timestep *ts = selframe(ctxt->atom_sel_mol, ctxt->which_frame);
00675 if (!ts) {
00676 msgErr << "No timestep available for 'within' search!" << sendmsg;
00677 return;
00678 }
00679 for (i=0; i<num; ++i) others.append(1);
00680 if (eval(node->left, num, &others[0])) {
00681 msgErr << "eval of a 'within' returned data when it shouldn't have." << sendmsg;
00682 return;
00683 }
00684
00685
00686 const float * pos=ts->pos;
00687 for (i=0; i<num; i++) {
00688 coords.append(pos[0]);
00689 coords.append(pos[1]);
00690 coords.append(pos[2]);
00691 pos += 3;
00692 repflgs.append(flgs[i]);
00693 }
00694
00695
00696 float min[3], max[3];
00697 if (!find_minmax_selected(num, &others[0], ts->pos,
00698 min[0], min[1], min[2], max[0], max[1], max[2])) {
00699 memset(flgs, 0, num*sizeof(int));
00700 return;
00701 }
00702
00703
00704 const float cutoff = (float)node->dval;
00705 for (i=0; i<3; i++) {
00706 min[i] -= cutoff;
00707 max[i] += cutoff;
00708 }
00709
00710
00711 float A[3], B[3], C[3];
00712 ts->get_transform_vectors(A, B, C);
00713 for (i=-1; i<=1; i++) {
00714 float v1[3];
00715 vec_scale(v1, i, A);
00716 for (int j=-1; j<=1; j++) {
00717 float v2[3];
00718 vec_scale(v2, j, B);
00719 for (int k=-1; k<=1; k++) {
00720
00721 if (!i && !j && !k) continue;
00722 float v3[3];
00723 vec_scale(v3, k, C);
00724 float vx = v1[0] + v2[0] + v3[0];
00725 float vy = v1[1] + v2[1] + v3[1];
00726 float vz = v1[2] + v2[2] + v3[2];
00727 pos = ts->pos;
00728 for (int ind=0; ind<num; ind++) {
00729 if (flgs[ind]) {
00730 const float x = pos[0] + vx;
00731 const float y = pos[1] + vy;
00732 const float z = pos[2] + vz;
00733 if (x>min[0] && x<=max[0] &&
00734 y>min[1] && y<=max[1] &&
00735 z>min[2] && z<=max[2]) {
00736 repindexes.append(ind);
00737 coords.append(x);
00738 coords.append(y);
00739 coords.append(z);
00740 repflgs.append(1);
00741 others.append(0);
00742 }
00743 }
00744 pos += 3;
00745 }
00746 }
00747 }
00748 }
00749
00750 find_within(&coords[0], &repflgs[0], &others[0], others.num(), cutoff);
00751
00752
00753 memcpy(flgs, &repflgs[0], num*sizeof(int));
00754
00755
00756 for (i=0; i<repindexes.num(); i++) {
00757 if (repflgs[num+i]) {
00758 flgs[repindexes[i]] = 1;
00759 }
00760 }
00761 }
00762
00763
00764 void ParseTree::eval_within(atomparser_node *node, int num, int *flgs) {
00765
00766 int *others = new int[num];
00767 int i;
00768 for (i=0; i<num; ++i)
00769 others[i] = 1;
00770
00771 if (eval(node->left, num, others)) {
00772 delete [] others;
00773 msgErr << "eval of a 'within' returned data when it shouldn't have." << sendmsg;
00774 return;
00775 }
00776
00777
00778 atomsel_ctxt *ctxt = (atomsel_ctxt *)context;
00779 Timestep *ts = selframe(ctxt->atom_sel_mol, ctxt->which_frame);
00780 if (!ts) {
00781 msgErr << "No timestep available for 'within' search!" << sendmsg;
00782 return;
00783 }
00784
00785 find_within(ts->pos, flgs, others, num, (float) node->dval);
00786 delete [] others;
00787 }
00788
00789
00790
00791
00792 symbol_data *ParseTree::eval(atomparser_node *node, int num, int *flgs) {
00793 int i;
00794 int *flg1, *flg2;
00795 symbol_data *tmp;
00796 switch(node->node_type) {
00797 case AND:
00798 eval(node->left, num, flgs);
00799 eval(node->right, num, flgs);
00800 return NULL;
00801
00802 case NOT:
00803 flg1 = new int[num];
00804 memcpy(flg1, flgs, num*sizeof(int));
00805
00806 eval(node->left, num, flg1);
00807
00808 for (i=num-1; i>=0; i--) {
00809 if (flgs[i])
00810 flgs[i] = !flg1[i];
00811 }
00812 delete [] flg1;
00813 break;
00814
00815 case OR:
00816 flg1 = new int[num];
00817 memcpy(flg1, flgs, num*sizeof(int));
00818 eval(node->left, num, flg1);
00819 flg2 = new int[num];
00820 memcpy(flg2, flgs, num*sizeof(int));
00821 eval(node->right, num, flg2);
00822 for (i=num-1; i>=0; i--) {
00823 flgs[i] = flgs[i] && (flg1[i] || flg2[i]);
00824 }
00825 delete [] flg1;
00826 delete [] flg2;
00827 break;
00828
00829 case FLOAT:
00830 tmp = new symbol_data(SymbolTableElement::IS_FLOAT, 1);
00831 tmp->dval[0] = node->dval;
00832 return tmp;
00833
00834 case INT:
00835 tmp = new symbol_data(SymbolTableElement::IS_INT, 1);
00836 tmp->ival[0] = node->ival;
00837 return tmp;
00838
00839 case WORD:
00840 tmp = new symbol_data(SymbolTableElement::IS_STRING, 1);
00841 tmp->sval[0] = (char *)(const char *)node->sele.s;
00842 return tmp;
00843
00844 case KEY:
00845 return eval_key(node, num, flgs);
00846
00847 case STRFCTN:
00848 eval_stringfctn(node, num, flgs);
00849 break;
00850
00851 case FUNC:
00852 {
00853
00854
00855
00856 symbol_data *inp = eval(node->left, num, flgs);
00857 inp->convert(SymbolTableElement::IS_FLOAT);
00858
00859
00860 symbol_data *ret = new symbol_data(SymbolTableElement::IS_FLOAT, num);
00861 SymbolTableElement *elem = table->fctns.data(node->extra_type);
00862
00863
00864
00865
00866 if (inp->num == num) {
00867 for (i=0; i<num; i++)
00868 ret->dval[i] = elem->fctn(inp->dval[i]);
00869 } else {
00870
00871
00872 double d = elem->fctn(inp->dval[0]);
00873 for (i=0; i<num; i++)
00874 ret->dval[i] = d;
00875 }
00876 delete inp;
00877 return ret;
00878 }
00879
00880 case ADD:
00881 case SUB:
00882 case MULT:
00883 case MOD:
00884 case EXP:
00885 case DIV:
00886 return eval_mathop(node, num, flgs);
00887
00888 case UMINUS:
00889 tmp = eval(node->left, num, flgs);
00890 tmp->convert(SymbolTableElement::IS_FLOAT);
00891 for (i=0; i<tmp->num; i++) {
00892 tmp->dval[i] = -tmp->dval[i];
00893 }
00894 return tmp;
00895
00896 case COMPARE:
00897 eval_compare(node, num, flgs);
00898 break;
00899
00900 case WITHIN:
00901 eval_within(node, num, flgs);
00902 break;
00903
00904 case EXWITHIN:
00905 eval_exwithin(node, num, flgs);
00906 break;
00907
00908 case PBWITHIN:
00909 eval_pbwithin(node, num, flgs);
00910 break;
00911
00912 case SAME:
00913 eval_same(node, num, flgs);
00914 break;
00915
00916 case SINGLE:
00917 eval_single(node, num, flgs);
00918 break;
00919
00920 default:
00921 msgWarn << "ParseTree::eval() unknown node type: " << node->node_type << sendmsg;
00922 break;
00923 }
00924
00925 return NULL;
00926 }
00927
00928
00929
00930 void ParseTree::eval_find_recursion(atomparser_node *node, int *found,
00931 hash_t *hash) {
00932
00933
00934
00935 switch (node->node_type) {
00936 case AND:
00937 case OR:
00938 eval_find_recursion(node->left, found, hash);
00939 eval_find_recursion(node->right, found, hash);
00940
00941
00942 break;
00943
00944 case NOT:
00945 case UMINUS:
00946 case WITHIN:
00947 case EXWITHIN:
00948 case SAME:
00949 case FUNC:
00950 eval_find_recursion(node->left, found, hash);
00951 break;
00952
00953 case SINGLE:
00954 {
00955 const char *thisword = table->fctns.name(node->extra_type);
00956 const char *macro = table->get_custom_singleword(thisword);
00957 if (macro) {
00958 if (hash_insert(hash, thisword, 0) != HASH_FAIL) {
00959 *found = 1;
00960 } else {
00961 ParseTree *subtree = table->parse(macro);
00962 if (subtree != NULL) {
00963 eval_find_recursion(subtree->tree, found, hash);
00964 delete subtree;
00965 } else {
00966
00967
00968
00969
00970 msgErr << "ParseTree) internal processing error, NULL "
00971 << "subtree value while checking recursion" << sendmsg;
00972 }
00973 hash_delete(hash, thisword);
00974 }
00975 }
00976 }
00977 break;
00978 }
00979 }
00980
00981
00982
00983 int ParseTree::find_recursion(const char *head) {
00984 hash_t hash;
00985 hash_init(&hash, 10);
00986 hash_insert(&hash, head, 0);
00987 int found = 0;
00988 eval_find_recursion(tree, &found, &hash);
00989 hash_destroy(&hash);
00990 return found;
00991 }
00992
00993
00994
00995
00996
00997 int ParseTree::evaluate(int num_atoms, int *flgs) {
00998 int num = num_atoms;
00999 if (!tree || num < 0 ) {
01000 return 0;
01001 }
01002
01003
01004 for (int i=0; i<num; i++) {
01005 flgs[i] = 1;
01006 }
01007
01008
01009 symbol_data *retdat = eval(tree, num, flgs);
01010 if (retdat) {
01011 msgErr << "Atom selection returned data when it shouldn't\n" << sendmsg;
01012 delete retdat;
01013 }
01014
01015 return 1;
01016 }
01017
01018
01019
01020 void symbol_data::make_space(void) {
01021 free_space();
01022 switch(type) {
01023 case SymbolTableElement::IS_FLOAT:
01024 dval = new double[num];
01025 break;
01026
01027 case SymbolTableElement::IS_INT:
01028 ival = new int[num];
01029 break;
01030
01031 case SymbolTableElement::IS_STRING:
01032 sval = new char *[num];
01033 memset(sval, 0, num*sizeof(char *));
01034 break;
01035 }
01036 }
01037
01038
01039
01040 void symbol_data::free_space(void) {
01041 switch (type) {
01042 case SymbolTableElement::IS_FLOAT:
01043 if (dval)
01044 delete [] dval;
01045 dval = NULL;
01046 break;
01047
01048 case SymbolTableElement::IS_INT:
01049 if (ival)
01050 delete [] ival;
01051 ival = NULL;
01052 break;
01053
01054 case SymbolTableElement::IS_STRING:
01055 if (sval) {
01056
01057 if (free_sval)
01058 for (int i=0; i<num; i++) free(sval[i]);
01059
01060 delete [] sval;
01061 sval = NULL;
01062 }
01063 free_sval = 0;
01064 break;
01065
01066 default:
01067 msgErr << "Unknown data type " << (int)type
01068 << " in symbol_data::free_space" << sendmsg;
01069 }
01070 }
01071
01072
01073
01074 symbol_data::symbol_data(SymbolTableElement::symtype new_type, int new_num) {
01075 type = new_type;
01076 num = new_num;
01077 dval = NULL;
01078 ival = NULL;
01079 sval = NULL;
01080 free_sval = 0;
01081 make_space();
01082 }
01083
01084
01085 symbol_data::~symbol_data(void) {
01086 free_space();
01087 }
01088
01089
01090 void symbol_data::convert(SymbolTableElement::symtype totype) {
01091
01092 if (totype == type)
01093 return;
01094
01095
01096 if (totype == SymbolTableElement::IS_FLOAT) {
01097 double *tmp = new double[num];
01098 if (type == SymbolTableElement::IS_INT) {
01099 for (int i=num-1; i>=0; i--) {
01100 tmp[i] = (double) ival[i];
01101 }
01102 } else {
01103 for (int i=num-1; i>=0; i--) {
01104
01105
01106
01107
01108
01109
01110
01111
01112 if (sval[i] != NULL) {
01113 tmp[i] = atof(sval[i]);
01114 } else {
01115 for (int j=num-1; j>=0; j--) {
01116 tmp[i] = 0.0f;
01117 }
01118 msgErr << "ParseTree) internal processing error, NULL string value "
01119 << "while converting to floating point" << sendmsg;
01120 break;
01121 }
01122 }
01123 }
01124 free_space();
01125 type = totype;
01126 dval = tmp;
01127 return;
01128 }
01129
01130
01131 if (totype == SymbolTableElement::IS_STRING) {
01132 char **tmp = new char*[num];
01133 memset(tmp, 0, num*sizeof(char *));
01134 char s[100];
01135 if (type == SymbolTableElement::IS_INT) {
01136 for (int i=num-1; i>=0; i--) {
01137 sprintf(s, "%ld", (long) ival[i]);
01138 tmp[i] = strdup(s);
01139 }
01140 } else {
01141 for (int i=num-1; i>=0; i--) {
01142 sprintf(s, "%f", (double) dval[i]);
01143 tmp[i] = strdup(s);
01144 }
01145 }
01146 free_space();
01147 type = totype;
01148 sval = tmp;
01149 free_sval = TRUE;
01150 return;
01151 }
01152
01153
01154 if (totype == SymbolTableElement::IS_INT) {
01155 int *tmp = new int[num];
01156 if (type == SymbolTableElement::IS_FLOAT) {
01157 for (int i=num-1; i>=0; i--) {
01158 tmp[i] = (int) dval[i];
01159 }
01160 } else {
01161 for (int i=num-1; i>=0; i--) {
01162
01163
01164
01165
01166
01167
01168
01169
01170 if (sval[i] != NULL) {
01171 tmp[i] = atoi(sval[i]);
01172 } else {
01173 for (int j=num-1; j>=0; j--) {
01174 tmp[i] = 0;
01175 }
01176 msgErr << "ParseTree) internal processing error, NULL string value "
01177 << "while converting to integer" << sendmsg;
01178 break;
01179 }
01180 }
01181 }
01182 free_space();
01183 type = totype;
01184 ival = tmp;
01185 return;
01186 }
01187 }
01188