#include #include #include #include #include "hashtable.h" #include "token.h" #include "node.h" node::node(node_type t, string s, int v): token(t, s, v) { } node * node::var(string s) { return new node(tvariable, s, 0); } node * node::num(int v) { return new node(tnumber, "", v); } node * node::op(string s) { return new node(toperator, s, 0); } node * node::err(string s) { return new node(terror, s, 0); } node * node::add(node * n) { links.push_back(n); return this; } int node::getnumlinks() { return links.size(); } node * node::getlink(int i) { return links[i]; } int power(int a, int b) { if (b == 0) { if (a == 0) cout << "Error! 0^0\n"; return 1; } if (b < 0) { if (a == 0) cout << "Error! 0^negative\n"; if (a == 1) return 1; if (a == -1) { if (b & 1) return -1; return 1; } return 0; } int p = 1; int m = a; while (b > 0) { if (b & 1) p *= m; m *= m; b >>= 1; } return p; } int node::evaluate(hashtable & mem) { node_type t = gettype(); if (t == terror) { cerr << "Error! " << getstring() << "\n"; return 0; } else if (t == tnumber) return getvalue(); else if (t == tvariable) { int * p = mem.find(getstring()); if (p == NULL) { cerr << "Error! undefined variable " << getstring() << "\n"; return 0; } return * p; } else if (t == toperator) { int L = getlink(0)->evaluate(mem); int R = getlink(1)->evaluate(mem); char c = getstring()[0]; switch (c) { case '+': return L + R; case '-': return L - R; case '*': return L * R; case '/': { if (R == 0) { cout << "division by zero!\n"; return 0; } return L / R; } case '^': return power(L, R); default: { cout << "error operator '" << c << "'\n"; return 0; } } } else { cerr << "Error evaluate node type " << gettype() << "\n"; return 0; } } void node::print() { node_type t = gettype(); if (t == tnumber) cout << getvalue(); else if (t == tvariable) cout << getstring(); else if (t == toperator) { cout << "("; getlink(0)->print(); cout << getstring(); getlink(1)->print(); cout << ")"; } } void node::print1(int depth) { cout << setw(depth*3) << " "; node_type t = gettype(); if (t == tnumber) cout << getvalue() << "\n"; else if (t == tvariable) cout << getstring() << "\n"; else if (t == toperator) { cout << getstring() << "\n"; int num = getnumlinks(); for (int i = 0; i < num; i += 1) getlink(i)->print1(depth+1); } }