Calculator.cc revision 10447
110447Snilay@cs.wisc.edu#include "Calculator.h" 210447Snilay@cs.wisc.edu 310447Snilay@cs.wisc.edu#include <cctype> 410447Snilay@cs.wisc.edu#include <iostream> 510447Snilay@cs.wisc.edu 610447Snilay@cs.wisc.edunamespace LibUtil 710447Snilay@cs.wisc.edu{ 810447Snilay@cs.wisc.edu using std::cout; 910447Snilay@cs.wisc.edu using std::endl; 1010447Snilay@cs.wisc.edu using std::scientific; 1110447Snilay@cs.wisc.edu 1210447Snilay@cs.wisc.edu Calculator::Calculator() 1310447Snilay@cs.wisc.edu { 1410447Snilay@cs.wisc.edu m_reserved_chars_ = "+-*/;=()\\"; 1510447Snilay@cs.wisc.edu } 1610447Snilay@cs.wisc.edu 1710447Snilay@cs.wisc.edu Calculator::~Calculator() 1810447Snilay@cs.wisc.edu {} 1910447Snilay@cs.wisc.edu 2010447Snilay@cs.wisc.edu void Calculator::reset() 2110447Snilay@cs.wisc.edu { 2210447Snilay@cs.wisc.edu m_var_.clear(); 2310447Snilay@cs.wisc.edu return; 2410447Snilay@cs.wisc.edu } 2510447Snilay@cs.wisc.edu 2610447Snilay@cs.wisc.edu void Calculator::evaluateString(const String& str_) 2710447Snilay@cs.wisc.edu { 2810447Snilay@cs.wisc.edu istringstream ist(str_); 2910447Snilay@cs.wisc.edu while(ist) 3010447Snilay@cs.wisc.edu { 3110447Snilay@cs.wisc.edu getToken(ist); 3210447Snilay@cs.wisc.edu if(m_curr_token_ == END) break; 3310447Snilay@cs.wisc.edu if(m_curr_token_ == SEP) continue; 3410447Snilay@cs.wisc.edu if((m_curr_token_ == NAME) && (m_value_string_ == "print")) 3510447Snilay@cs.wisc.edu { 3610447Snilay@cs.wisc.edu getToken(ist); 3710447Snilay@cs.wisc.edu 3810447Snilay@cs.wisc.edu if(m_curr_token_ == STRING) 3910447Snilay@cs.wisc.edu { 4010447Snilay@cs.wisc.edu String print_str = m_value_string_; 4110447Snilay@cs.wisc.edu 4210447Snilay@cs.wisc.edu getToken(ist); 4310447Snilay@cs.wisc.edu if(m_curr_token_ == SEP) 4410447Snilay@cs.wisc.edu { 4510447Snilay@cs.wisc.edu cout << print_str << endl; 4610447Snilay@cs.wisc.edu } 4710447Snilay@cs.wisc.edu else 4810447Snilay@cs.wisc.edu { 4910447Snilay@cs.wisc.edu double v = expr(ist, false); 5010447Snilay@cs.wisc.edu cout << scientific << print_str << v << endl; 5110447Snilay@cs.wisc.edu } 5210447Snilay@cs.wisc.edu } 5310447Snilay@cs.wisc.edu else 5410447Snilay@cs.wisc.edu { 5510447Snilay@cs.wisc.edu double v = expr(ist, false); 5610447Snilay@cs.wisc.edu cout << scientific << v << endl; 5710447Snilay@cs.wisc.edu } 5810447Snilay@cs.wisc.edu } 5910447Snilay@cs.wisc.edu else 6010447Snilay@cs.wisc.edu { 6110447Snilay@cs.wisc.edu expr(ist, false); 6210447Snilay@cs.wisc.edu } 6310447Snilay@cs.wisc.edu } 6410447Snilay@cs.wisc.edu return; 6510447Snilay@cs.wisc.edu } 6610447Snilay@cs.wisc.edu 6710447Snilay@cs.wisc.edu Calculator::Token Calculator::getToken(istringstream& ist_) 6810447Snilay@cs.wisc.edu { 6910447Snilay@cs.wisc.edu char ch; 7010447Snilay@cs.wisc.edu do 7110447Snilay@cs.wisc.edu { 7210447Snilay@cs.wisc.edu ist_.get(ch); 7310447Snilay@cs.wisc.edu if(!ist_) 7410447Snilay@cs.wisc.edu { 7510447Snilay@cs.wisc.edu m_curr_token_ = END; 7610447Snilay@cs.wisc.edu return m_curr_token_; 7710447Snilay@cs.wisc.edu } 7810447Snilay@cs.wisc.edu } 7910447Snilay@cs.wisc.edu while(ch != '\n' && isspace(ch)); 8010447Snilay@cs.wisc.edu 8110447Snilay@cs.wisc.edu switch(ch) 8210447Snilay@cs.wisc.edu { 8310447Snilay@cs.wisc.edu case '\n': 8410447Snilay@cs.wisc.edu m_curr_token_ = END; 8510447Snilay@cs.wisc.edu return m_curr_token_; 8610447Snilay@cs.wisc.edu case ';': 8710447Snilay@cs.wisc.edu m_curr_token_ = SEP; 8810447Snilay@cs.wisc.edu return m_curr_token_; 8910447Snilay@cs.wisc.edu case '*': 9010447Snilay@cs.wisc.edu case '/': 9110447Snilay@cs.wisc.edu case '+': 9210447Snilay@cs.wisc.edu case '-': 9310447Snilay@cs.wisc.edu case '(': 9410447Snilay@cs.wisc.edu case ')': 9510447Snilay@cs.wisc.edu case '=': 9610447Snilay@cs.wisc.edu m_curr_token_ = Token(ch); 9710447Snilay@cs.wisc.edu return m_curr_token_; 9810447Snilay@cs.wisc.edu case '0': case '1': case '2': case '3': case '4': 9910447Snilay@cs.wisc.edu case '5': case '6': case '7': case '8': case '9': 10010447Snilay@cs.wisc.edu case '.': 10110447Snilay@cs.wisc.edu ist_.putback(ch); 10210447Snilay@cs.wisc.edu ist_ >> m_value_number_; 10310447Snilay@cs.wisc.edu m_curr_token_ = NUMBER; 10410447Snilay@cs.wisc.edu return m_curr_token_; 10510447Snilay@cs.wisc.edu case '"': 10610447Snilay@cs.wisc.edu ist_.get(ch); 10710447Snilay@cs.wisc.edu m_value_string_ = ""; 10810447Snilay@cs.wisc.edu while(ist_ && ('"' != ch)) 10910447Snilay@cs.wisc.edu { 11010447Snilay@cs.wisc.edu m_value_string_ += String(1, ch); 11110447Snilay@cs.wisc.edu ist_.get(ch); 11210447Snilay@cs.wisc.edu } 11310447Snilay@cs.wisc.edu m_curr_token_ = STRING; 11410447Snilay@cs.wisc.edu return m_curr_token_; 11510447Snilay@cs.wisc.edu case '$': 11610447Snilay@cs.wisc.edu ist_.get(ch); 11710447Snilay@cs.wisc.edu ASSERT((ch == '('), "[Error] Bad token: '(' expected"); 11810447Snilay@cs.wisc.edu ist_.get(ch); 11910447Snilay@cs.wisc.edu m_value_string_ = ""; 12010447Snilay@cs.wisc.edu while(ist_ && (!isspace(ch)) && (')' != ch)) 12110447Snilay@cs.wisc.edu { 12210447Snilay@cs.wisc.edu m_value_string_ += String(1, ch); 12310447Snilay@cs.wisc.edu ist_.get(ch); 12410447Snilay@cs.wisc.edu } 12510447Snilay@cs.wisc.edu m_curr_token_ = NAME2; 12610447Snilay@cs.wisc.edu return m_curr_token_; 12710447Snilay@cs.wisc.edu default: 12810447Snilay@cs.wisc.edu if(isalpha(ch)) 12910447Snilay@cs.wisc.edu { 13010447Snilay@cs.wisc.edu m_value_string_ = ch; 13110447Snilay@cs.wisc.edu ist_.get(ch); 13210447Snilay@cs.wisc.edu while(ist_ && (isalnum(ch) || ('_' == ch))) 13310447Snilay@cs.wisc.edu { 13410447Snilay@cs.wisc.edu m_value_string_ += String(1, ch); 13510447Snilay@cs.wisc.edu ist_.get(ch); 13610447Snilay@cs.wisc.edu } 13710447Snilay@cs.wisc.edu ist_.putback(ch); 13810447Snilay@cs.wisc.edu m_curr_token_ = NAME; 13910447Snilay@cs.wisc.edu return m_curr_token_; 14010447Snilay@cs.wisc.edu } 14110447Snilay@cs.wisc.edu else 14210447Snilay@cs.wisc.edu { 14310447Snilay@cs.wisc.edu String error_msg = "[Error] Bad token: '" + String(ch) + "'"; 14410447Snilay@cs.wisc.edu throw Exception(error_msg); 14510447Snilay@cs.wisc.edu } 14610447Snilay@cs.wisc.edu } 14710447Snilay@cs.wisc.edu } 14810447Snilay@cs.wisc.edu 14910447Snilay@cs.wisc.edu double Calculator::prim(istringstream& ist_, bool is_get_) 15010447Snilay@cs.wisc.edu { 15110447Snilay@cs.wisc.edu if(is_get_) 15210447Snilay@cs.wisc.edu { 15310447Snilay@cs.wisc.edu getToken(ist_); 15410447Snilay@cs.wisc.edu } 15510447Snilay@cs.wisc.edu 15610447Snilay@cs.wisc.edu double v; 15710447Snilay@cs.wisc.edu switch(m_curr_token_) 15810447Snilay@cs.wisc.edu { 15910447Snilay@cs.wisc.edu case NUMBER: 16010447Snilay@cs.wisc.edu v = m_value_number_; 16110447Snilay@cs.wisc.edu getToken(ist_); 16210447Snilay@cs.wisc.edu return v; 16310447Snilay@cs.wisc.edu case NAME: 16410447Snilay@cs.wisc.edu if(getToken(ist_) == ASSIGN) 16510447Snilay@cs.wisc.edu { 16610447Snilay@cs.wisc.edu String var_name = m_value_string_; 16710447Snilay@cs.wisc.edu v = expr(ist_, true); 16810447Snilay@cs.wisc.edu m_var_.set(var_name, v); 16910447Snilay@cs.wisc.edu } 17010447Snilay@cs.wisc.edu else 17110447Snilay@cs.wisc.edu { 17210447Snilay@cs.wisc.edu v = m_var_.get(m_value_string_); 17310447Snilay@cs.wisc.edu } 17410447Snilay@cs.wisc.edu return v; 17510447Snilay@cs.wisc.edu case NAME2: 17610447Snilay@cs.wisc.edu v = getEnvVar(m_value_string_); 17710447Snilay@cs.wisc.edu getToken(ist_); 17810447Snilay@cs.wisc.edu return v; 17910447Snilay@cs.wisc.edu case MINUS: 18010447Snilay@cs.wisc.edu return -prim(ist_, true); 18110447Snilay@cs.wisc.edu case LP: 18210447Snilay@cs.wisc.edu v = expr(ist_, true); 18310447Snilay@cs.wisc.edu ASSERT((m_curr_token_ == RP), "[Error] ')' expected"); 18410447Snilay@cs.wisc.edu getToken(ist_); 18510447Snilay@cs.wisc.edu return v; 18610447Snilay@cs.wisc.edu default: 18710447Snilay@cs.wisc.edu ASSERT(0, "[Error] primary expected, get: '" + String(int(m_curr_token_)) + "'"); 18810447Snilay@cs.wisc.edu } 18910447Snilay@cs.wisc.edu } 19010447Snilay@cs.wisc.edu 19110447Snilay@cs.wisc.edu double Calculator::term(istringstream& ist_, bool is_get_) 19210447Snilay@cs.wisc.edu { 19310447Snilay@cs.wisc.edu double left = prim(ist_, is_get_); 19410447Snilay@cs.wisc.edu 19510447Snilay@cs.wisc.edu while(1) 19610447Snilay@cs.wisc.edu { 19710447Snilay@cs.wisc.edu double d; 19810447Snilay@cs.wisc.edu switch(m_curr_token_) 19910447Snilay@cs.wisc.edu { 20010447Snilay@cs.wisc.edu case MUL: 20110447Snilay@cs.wisc.edu left *= prim(ist_, true); 20210447Snilay@cs.wisc.edu break; 20310447Snilay@cs.wisc.edu case DIV: 20410447Snilay@cs.wisc.edu d = prim(ist_, true); 20510447Snilay@cs.wisc.edu ASSERT(d, "[Error] divided by 0"); 20610447Snilay@cs.wisc.edu left /= d; 20710447Snilay@cs.wisc.edu break; 20810447Snilay@cs.wisc.edu default: 20910447Snilay@cs.wisc.edu return left; 21010447Snilay@cs.wisc.edu } 21110447Snilay@cs.wisc.edu } 21210447Snilay@cs.wisc.edu } 21310447Snilay@cs.wisc.edu 21410447Snilay@cs.wisc.edu double Calculator::expr(istringstream& ist_, bool is_get_) 21510447Snilay@cs.wisc.edu { 21610447Snilay@cs.wisc.edu double left = term(ist_, is_get_); 21710447Snilay@cs.wisc.edu 21810447Snilay@cs.wisc.edu while(1) 21910447Snilay@cs.wisc.edu { 22010447Snilay@cs.wisc.edu switch(m_curr_token_) 22110447Snilay@cs.wisc.edu { 22210447Snilay@cs.wisc.edu case PLUS: 22310447Snilay@cs.wisc.edu left += term(ist_, true); 22410447Snilay@cs.wisc.edu break; 22510447Snilay@cs.wisc.edu case MINUS: 22610447Snilay@cs.wisc.edu left -= term(ist_, true); 22710447Snilay@cs.wisc.edu break; 22810447Snilay@cs.wisc.edu default: 22910447Snilay@cs.wisc.edu return left; 23010447Snilay@cs.wisc.edu } 23110447Snilay@cs.wisc.edu } 23210447Snilay@cs.wisc.edu } 23310447Snilay@cs.wisc.edu 23410447Snilay@cs.wisc.edu double Calculator::getEnvVar(const String& var_name_) const 23510447Snilay@cs.wisc.edu { 23610447Snilay@cs.wisc.edu return m_var_.get(var_name_); 23710447Snilay@cs.wisc.edu } 23810447Snilay@cs.wisc.edu} // namespace LibUtil 23910447Snilay@cs.wisc.edu 240