/* call parse_expsimple() repeatedly until the entire symbol stack is reduced to a single numeric symbol. */ double ModCalc::parse_explist (void) { while (error[0] == 0) if (parse_expsimple ()) { symbol_type *symbol = pop_symbol (); if (symbol == NULL || symbol->type != S_NUM) { snprintf (error, MSG_SIZE, "FUNCTION PARAMETER ERROR!"); break; } return symbol->value; } return 0; }
/* parse a simple expression (<num><operation><num>) from the symbol stack and push the result. expands <num> to identifiers (constants, variables or functions), and to another expression inside braces. return 1 if S_EOF is found, 0 otherwise. */ bool ModCalc::parse_expsimple (void) { double d = 0; bool lvalue = 0; symbol_type *symbol, *op = NULL, *var = NULL; while (1) { symbol = pop_symbol (); if (symbol == NULL) { snprintf (error, MSG_SIZE, "STACK ERROR!"); error_pos = 0; return 0; } error_pos = symbol->pos; if (symbol->type == S_EOF) { if (!lvalue || op != NULL || braces != 0) { snprintf (error, MSG_SIZE, "unexpected end of expression"); break; } push_symbol (new symbol_type (symbol->pos, d)); delete symbol; return 1; } else if (symbol->type == S_OP) { if (symbol->op == OP_ASSIGN) { if (var == NULL) { snprintf (error, MSG_SIZE, "non-variable lvalue in assignment"); break; } } else { if (op != NULL || (!lvalue && symbol->op != OP_PLUS && symbol->op != OP_MINUS)) { if (op != NULL) snprintf (error, MSG_SIZE, "missing rvalue for operator"); else snprintf (error, MSG_SIZE, "missing lvalue for operator"); break; } if (!lvalue && (symbol->op == OP_PLUS || symbol->op == OP_MINUS)) { d = 0; lvalue = 1; } } op = symbol; } else if (symbol->type == S_NUM) { if (op == NULL) { if (lvalue) { snprintf (error, MSG_SIZE, "two consecutive values"); break; } d = symbol->value; lvalue = 1; delete symbol; continue; } if (top != NULL && top->type == S_OP && top->priority > op->priority) { push_symbol (new symbol_type (symbol->pos, symbol->value)); parse_expsimple (); if (error[0] != 0) break; delete symbol; continue; } switch (op->op) { case OP_ASSIGN: d = symbol->value; var_type *v; vars.rewind (); while ((v = (var_type *)vars.next ()) != NULL) if (var->id == v->name) break; if (v != NULL) { v->value = d; v->time = get_time (); } else { vars.add ((void *)new var_type (var->id, d)); if (vars.count () == VARS_MAX) { time_t t_old = -1; var_type *v_old = NULL; vars.rewind (); while ((v = (var_type *)vars.next ()) != NULL) if (v->time < t_old) { t_old = v->time; v_old = v; } vars.del ((void *)v_old); } } delete var; var = NULL; break; case OP_PLUS: d += symbol->value; break; case OP_MINUS: d -= symbol->value; break; case OP_TIMES: d *= symbol->value; break; case OP_DIV: d /= symbol->value; break; case OP_MOD: d = fmod (d, symbol->value); break; case OP_POW: d = pow (d, symbol->value); break; case OP_SHIFT_L: d = ((unsigned long int)d) << ((unsigned long int)symbol->value); break; case OP_SHIFT_R: d = ((unsigned long int)d) >> ((unsigned long int)symbol->value); break; case OP_AND: d = ((unsigned long int)d) & ((unsigned long int)symbol->value); break; case OP_OR: d = ((unsigned long int)d) | ((unsigned long int)symbol->value); break; } push_symbol (new symbol_type (symbol->pos, d)); delete op; delete symbol; return 0; } else if (symbol->type == S_BRACE_L) { int old_braces = braces; braces++; while (braces != old_braces) { parse_expsimple (); if (error[0] != 0) break; } delete symbol; } else if (symbol->type == S_BRACE_R) { if (!lvalue) snprintf (error, MSG_SIZE, "missing value in braces"); else if (op != NULL) snprintf (error, MSG_SIZE, "missing rvalue for operator"); else if (braces == 0) snprintf (error, MSG_SIZE, "extra ')' used"); else { braces--; push_symbol (new symbol_type (symbol->pos, d)); delete symbol; if (op != NULL) delete op; return 0; } break; } else if (symbol->type == S_ID) { if (parse_exp_id (symbol)) { if (lvalue) { snprintf (error, MSG_SIZE, "invalid lvalue in assignment"); break; } var = symbol; } if (error[0] != 0) break; } }
void clear_table(void) { _symbol *entry; while ((entry = pop_symbol())) clear_entry(entry); }