| 1/* Copyright (c) 2012 Massachusetts Institute of Technology 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to deal 5 * in the Software without restriction, including without limitation the rights 6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 * copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 * THE SOFTWARE. 20 */ 21
|
1#include "Calculator.h" 2 3#include <cctype> 4#include <iostream> 5 6namespace LibUtil 7{ 8 using std::cout; 9 using std::endl; 10 using std::scientific; 11 12 Calculator::Calculator() 13 { 14 m_reserved_chars_ = "+-*/;=()\\"; 15 } 16 17 Calculator::~Calculator() 18 {} 19 20 void Calculator::reset() 21 { 22 m_var_.clear(); 23 return; 24 } 25
| 22#include "Calculator.h" 23 24#include <cctype> 25#include <iostream> 26 27namespace LibUtil 28{ 29 using std::cout; 30 using std::endl; 31 using std::scientific; 32 33 Calculator::Calculator() 34 { 35 m_reserved_chars_ = "+-*/;=()\\"; 36 } 37 38 Calculator::~Calculator() 39 {} 40 41 void Calculator::reset() 42 { 43 m_var_.clear(); 44 return; 45 } 46
|
26 void Calculator::evaluateString(const String& str_)
| 47 void Calculator::evaluateString(const String& str_, 48 const map<String, String> &config, 49 DSENT::Model *ms_model, 50 map<string, double> &outputs)
|
27 { 28 istringstream ist(str_);
| 51 { 52 istringstream ist(str_);
|
| 53
|
29 while(ist) 30 { 31 getToken(ist); 32 if(m_curr_token_ == END) break; 33 if(m_curr_token_ == SEP) continue; 34 if((m_curr_token_ == NAME) && (m_value_string_ == "print")) 35 { 36 getToken(ist); 37 38 if(m_curr_token_ == STRING) 39 { 40 String print_str = m_value_string_; 41 42 getToken(ist); 43 if(m_curr_token_ == SEP) 44 {
| 54 while(ist) 55 { 56 getToken(ist); 57 if(m_curr_token_ == END) break; 58 if(m_curr_token_ == SEP) continue; 59 if((m_curr_token_ == NAME) && (m_value_string_ == "print")) 60 { 61 getToken(ist); 62 63 if(m_curr_token_ == STRING) 64 { 65 String print_str = m_value_string_; 66 67 getToken(ist); 68 if(m_curr_token_ == SEP) 69 {
|
| 70 outputs[print_str] = 0;
|
45 cout << print_str << endl; 46 } 47 else 48 {
| 71 cout << print_str << endl; 72 } 73 else 74 {
|
49 double v = expr(ist, false); 50 cout << scientific << print_str << v << endl;
| 75 double v = expr(ist, false, config, ms_model); 76 outputs[print_str] = v; 77 cout << print_str << v << endl;
|
51 } 52 } 53 else 54 {
| 78 } 79 } 80 else 81 {
|
55 double v = expr(ist, false); 56 cout << scientific << v << endl;
| 82 double v = expr(ist, false, config, ms_model); 83 outputs["Missing Expression"] = v; 84 cout << v << endl;
|
57 } 58 } 59 else 60 {
| 85 } 86 } 87 else 88 {
|
61 expr(ist, false);
| 89 expr(ist, false, config, ms_model);
|
62 } 63 }
| 90 } 91 }
|
64 return;
| |
65 } 66 67 Calculator::Token Calculator::getToken(istringstream& ist_) 68 { 69 char ch; 70 do 71 { 72 ist_.get(ch); 73 if(!ist_) 74 { 75 m_curr_token_ = END; 76 return m_curr_token_; 77 } 78 } 79 while(ch != '\n' && isspace(ch)); 80 81 switch(ch) 82 { 83 case '\n': 84 m_curr_token_ = END; 85 return m_curr_token_; 86 case ';': 87 m_curr_token_ = SEP; 88 return m_curr_token_; 89 case '*': 90 case '/': 91 case '+': 92 case '-': 93 case '(': 94 case ')': 95 case '=': 96 m_curr_token_ = Token(ch); 97 return m_curr_token_; 98 case '0': case '1': case '2': case '3': case '4': 99 case '5': case '6': case '7': case '8': case '9': 100 case '.': 101 ist_.putback(ch); 102 ist_ >> m_value_number_; 103 m_curr_token_ = NUMBER; 104 return m_curr_token_; 105 case '"': 106 ist_.get(ch); 107 m_value_string_ = ""; 108 while(ist_ && ('"' != ch)) 109 { 110 m_value_string_ += String(1, ch); 111 ist_.get(ch); 112 } 113 m_curr_token_ = STRING; 114 return m_curr_token_; 115 case '$': 116 ist_.get(ch); 117 ASSERT((ch == '('), "[Error] Bad token: '(' expected"); 118 ist_.get(ch); 119 m_value_string_ = ""; 120 while(ist_ && (!isspace(ch)) && (')' != ch)) 121 { 122 m_value_string_ += String(1, ch); 123 ist_.get(ch); 124 } 125 m_curr_token_ = NAME2; 126 return m_curr_token_; 127 default: 128 if(isalpha(ch)) 129 { 130 m_value_string_ = ch; 131 ist_.get(ch); 132 while(ist_ && (isalnum(ch) || ('_' == ch))) 133 { 134 m_value_string_ += String(1, ch); 135 ist_.get(ch); 136 } 137 ist_.putback(ch); 138 m_curr_token_ = NAME; 139 return m_curr_token_; 140 } 141 else 142 { 143 String error_msg = "[Error] Bad token: '" + String(ch) + "'"; 144 throw Exception(error_msg); 145 } 146 } 147 } 148
| 92 } 93 94 Calculator::Token Calculator::getToken(istringstream& ist_) 95 { 96 char ch; 97 do 98 { 99 ist_.get(ch); 100 if(!ist_) 101 { 102 m_curr_token_ = END; 103 return m_curr_token_; 104 } 105 } 106 while(ch != '\n' && isspace(ch)); 107 108 switch(ch) 109 { 110 case '\n': 111 m_curr_token_ = END; 112 return m_curr_token_; 113 case ';': 114 m_curr_token_ = SEP; 115 return m_curr_token_; 116 case '*': 117 case '/': 118 case '+': 119 case '-': 120 case '(': 121 case ')': 122 case '=': 123 m_curr_token_ = Token(ch); 124 return m_curr_token_; 125 case '0': case '1': case '2': case '3': case '4': 126 case '5': case '6': case '7': case '8': case '9': 127 case '.': 128 ist_.putback(ch); 129 ist_ >> m_value_number_; 130 m_curr_token_ = NUMBER; 131 return m_curr_token_; 132 case '"': 133 ist_.get(ch); 134 m_value_string_ = ""; 135 while(ist_ && ('"' != ch)) 136 { 137 m_value_string_ += String(1, ch); 138 ist_.get(ch); 139 } 140 m_curr_token_ = STRING; 141 return m_curr_token_; 142 case '$': 143 ist_.get(ch); 144 ASSERT((ch == '('), "[Error] Bad token: '(' expected"); 145 ist_.get(ch); 146 m_value_string_ = ""; 147 while(ist_ && (!isspace(ch)) && (')' != ch)) 148 { 149 m_value_string_ += String(1, ch); 150 ist_.get(ch); 151 } 152 m_curr_token_ = NAME2; 153 return m_curr_token_; 154 default: 155 if(isalpha(ch)) 156 { 157 m_value_string_ = ch; 158 ist_.get(ch); 159 while(ist_ && (isalnum(ch) || ('_' == ch))) 160 { 161 m_value_string_ += String(1, ch); 162 ist_.get(ch); 163 } 164 ist_.putback(ch); 165 m_curr_token_ = NAME; 166 return m_curr_token_; 167 } 168 else 169 { 170 String error_msg = "[Error] Bad token: '" + String(ch) + "'"; 171 throw Exception(error_msg); 172 } 173 } 174 } 175
|
149 double Calculator::prim(istringstream& ist_, bool is_get_)
| 176 double Calculator::prim(istringstream& ist_, bool is_get_, 177 const map<String, String> &config, 178 DSENT::Model *ms_model)
|
150 { 151 if(is_get_) 152 { 153 getToken(ist_); 154 } 155 156 double v; 157 switch(m_curr_token_) 158 { 159 case NUMBER: 160 v = m_value_number_; 161 getToken(ist_); 162 return v; 163 case NAME: 164 if(getToken(ist_) == ASSIGN) 165 { 166 String var_name = m_value_string_;
| 179 { 180 if(is_get_) 181 { 182 getToken(ist_); 183 } 184 185 double v; 186 switch(m_curr_token_) 187 { 188 case NUMBER: 189 v = m_value_number_; 190 getToken(ist_); 191 return v; 192 case NAME: 193 if(getToken(ist_) == ASSIGN) 194 { 195 String var_name = m_value_string_;
|
167 v = expr(ist_, true);
| 196 v = expr(ist_, true, config, ms_model);
|
168 m_var_.set(var_name, v); 169 } 170 else 171 { 172 v = m_var_.get(m_value_string_); 173 } 174 return v; 175 case NAME2:
| 197 m_var_.set(var_name, v); 198 } 199 else 200 { 201 v = m_var_.get(m_value_string_); 202 } 203 return v; 204 case NAME2:
|
176 v = getEnvVar(m_value_string_);
| 205 v = getEnvVar(m_value_string_, config, ms_model);
|
177 getToken(ist_); 178 return v; 179 case MINUS:
| 206 getToken(ist_); 207 return v; 208 case MINUS:
|
180 return -prim(ist_, true);
| 209 return -prim(ist_, true, config, ms_model);
|
181 case LP:
| 210 case LP:
|
182 v = expr(ist_, true);
| 211 v = expr(ist_, true, config, ms_model);
|
183 ASSERT((m_curr_token_ == RP), "[Error] ')' expected"); 184 getToken(ist_); 185 return v; 186 default: 187 ASSERT(0, "[Error] primary expected, get: '" + String(int(m_curr_token_)) + "'"); 188 } 189 } 190
| 212 ASSERT((m_curr_token_ == RP), "[Error] ')' expected"); 213 getToken(ist_); 214 return v; 215 default: 216 ASSERT(0, "[Error] primary expected, get: '" + String(int(m_curr_token_)) + "'"); 217 } 218 } 219
|
191 double Calculator::term(istringstream& ist_, bool is_get_)
| 220 double Calculator::term(istringstream& ist_, bool is_get_, 221 const map<String, String> &config, 222 DSENT::Model *ms_model)
|
192 {
| 223 {
|
193 double left = prim(ist_, is_get_);
| 224 double left = prim(ist_, is_get_, config, ms_model);
|
194 195 while(1) 196 { 197 double d; 198 switch(m_curr_token_) 199 { 200 case MUL:
| 225 226 while(1) 227 { 228 double d; 229 switch(m_curr_token_) 230 { 231 case MUL:
|
201 left *= prim(ist_, true);
| 232 left *= prim(ist_, true, config, ms_model);
|
202 break; 203 case DIV:
| 233 break; 234 case DIV:
|
204 d = prim(ist_, true);
| 235 d = prim(ist_, true, config, ms_model);
|
205 ASSERT(d, "[Error] divided by 0"); 206 left /= d; 207 break; 208 default: 209 return left; 210 } 211 } 212 } 213
| 236 ASSERT(d, "[Error] divided by 0"); 237 left /= d; 238 break; 239 default: 240 return left; 241 } 242 } 243 } 244
|
214 double Calculator::expr(istringstream& ist_, bool is_get_)
| 245 double Calculator::expr(istringstream& ist_, bool is_get_, 246 const map<String, String> &config, 247 DSENT::Model *ms_model)
|
215 {
| 248 {
|
216 double left = term(ist_, is_get_);
| 249 double left = term(ist_, is_get_, config, ms_model);
|
217 218 while(1) 219 { 220 switch(m_curr_token_) 221 { 222 case PLUS:
| 250 251 while(1) 252 { 253 switch(m_curr_token_) 254 { 255 case PLUS:
|
223 left += term(ist_, true);
| 256 left += term(ist_, true, config, ms_model);
|
224 break; 225 case MINUS:
| 257 break; 258 case MINUS:
|
226 left -= term(ist_, true);
| 259 left -= term(ist_, true, config, ms_model);
|
227 break; 228 default: 229 return left; 230 } 231 } 232 } 233
| 260 break; 261 default: 262 return left; 263 } 264 } 265 } 266
|
234 double Calculator::getEnvVar(const String& var_name_) const
| 267 double Calculator::getEnvVar(const String& var_name_, 268 const map<String, String> &config, 269 DSENT::Model *ms_model) const
|
235 { 236 return m_var_.get(var_name_); 237 } 238} // namespace LibUtil
| 270 { 271 return m_var_.get(var_name_); 272 } 273} // namespace LibUtil
|
239
| |
| |