node_impl.cpp

Go to the documentation of this file.
00001 #include <iomanip>
00002 #include <iterator>
00003 #include <ostream>
00004 #include <sstream>
00005 
00006 #include "calc_error.hpp"
00007 #include "node.hpp"
00008 #include "node_impl.hpp"
00009 #include "variables.hpp"
00010 
00011 node_impl::node_impl()
00012 : refcount_(1)
00013 {}
00014 
00015 node_impl::~node_impl()
00016 {}
00017 
00018 void node_impl::print(std::ostream& stream, int indent)
00019 const
00020 {
00021   print_node(stream, indent);
00022 }
00023 
00024 double node_impl::evaluate()
00025 const
00026 {
00027   return evaluate_node();
00028 }
00029 
00030 std::string node_impl::to_string()
00031 const
00032 {
00033   return evaluate_string();
00034 }
00035 
00036 void node_impl::add_ref()
00037 {
00038   ++refcount_;
00039 }
00040 
00041 identifier_list const& node_impl::get_parameters()
00042 const
00043 {
00044   return evaluate_parameters();
00045 }
00046 
00047 void node_impl::del_ref()
00048 {
00049   --refcount_;
00050   if (refcount_ == 0)
00051     delete this;
00052 }
00053 
00054 std::string node_impl::evaluate_string()
00055 const
00056 {
00057   std::ostringstream stream;
00058   stream << evaluate();
00059   return stream.str();
00060 }
00061 
00062 identifier_list const& node_impl::evaluate_parameters()
00063 const
00064 {
00065   static identifier_list const empty;
00066   return empty;
00067 }
00068 
00069 void node_impl::save(std::ostream& stream)
00070 const
00071 {
00072   save_node(stream);
00073 }
00074 
00075 /* Factory function to create node_impl objects from a saved library file. */
00076 node_impl* node_impl::read_node(std::istream& stream)
00077 {
00078   std::string type;
00079   if (not (stream >> type))
00080     return 0;
00081   if (type == "void")
00082     return new node_void(stream);
00083   if (type == "number")
00084     return new node_number(stream);
00085   if (type == "identifier")
00086     return new node_identifier(stream);
00087   if (type == "function")
00088     return new node_function(stream);
00089   if (type == "call")
00090     return new node_function_call(stream);
00091   if (type == "negate")
00092     return new node_negate(stream);
00093   if (type == "add")
00094     return new node_add(stream);
00095   if (type == "subtract")
00096     return new node_subtract(stream);
00097   if (type == "multiply")
00098     return new node_multiply(stream);
00099   if (type == "divide")
00100     return new node_divide(stream);
00101 
00102   throw calc_error("unknown node type: " + type);
00103 }
00104 
00105 node_void::node_void()
00106 : node_impl()
00107 {}
00108 
00109 node_void::node_void(std::istream&)
00110 : node_impl()
00111 {}
00112 
00113 void node_void::print_node(std::ostream& stream, int indent)
00114 const
00115 {
00116   stream << std::setw(indent) << "" << "void\n";
00117 }
00118 
00119 double node_void::evaluate_node()
00120 const
00121 {
00122   return 0.0;
00123 }
00124 
00125 std::string node_void::evaluate_string()
00126 const
00127 {
00128   return std::string();
00129 }
00130 
00131 void node_void::save_node(std::ostream& stream)
00132 const
00133 {
00134   stream << "void\n";
00135 }
00136 
00137 node_number::node_number(double value)
00138 : node_impl(), value_(value)
00139 {}
00140 
00141 node_number::node_number(std::istream& stream)
00142 : node_impl()
00143 {
00144   if (not (stream >> value_))
00145     throw calc_error("malformed library file, cannot read number");
00146 }
00147 
00148 double node_number::value()
00149 const
00150 {
00151   return value_;
00152 }
00153 
00154 void node_number::print_node(std::ostream& stream, int indent)
00155 const
00156 {
00157   stream << std::setw(indent) << "" << value() << '\n';
00158 }
00159 
00160 double node_number::evaluate_node()
00161 const
00162 {
00163   return value();
00164 }
00165 
00166 void node_number::save_node(std::ostream& stream)
00167 const
00168 {
00169   stream << "number " << value() << '\n';
00170 }
00171 
00172 
00173 node_identifier::node_identifier(std::string const& name)
00174 : node_impl(), name_(name)
00175 {}
00176 
00177 node_identifier::node_identifier(std::istream& stream)
00178 : node_impl()
00179 {
00180   if (not (stream >> name_))
00181     throw calc_error("malformed library file, cannot read identifier");
00182 }
00183 
00184 std::string const& node_identifier::name()
00185 const
00186 {
00187   return name_;
00188 }
00189 
00190 void node_identifier::print_node(std::ostream& stream, int indent)
00191 const
00192 {
00193   stream << std::setw(indent) << "" << "identifier " << name() << '\n';
00194 }
00195 
00196 double node_identifier::evaluate_node()
00197 const
00198 {
00199   return get_variable(name()).evaluate();
00200 }
00201 
00202 std::string node_identifier::evaluate_string()
00203 const
00204 {
00205   return name();
00206 }
00207 
00208 void node_identifier::save_node(std::ostream& stream)
00209 const
00210 {
00211   stream << "identifier " << name() << '\n';
00212 }
00213 
00214 
00215 node_function::node_function(identifier_list const& parameters, node definition)
00216 : node_impl(), parameters_(parameters), definition_(definition)
00217 {}
00218 
00219 node_function::node_function(std::istream& stream)
00220 : node_impl()
00221 {
00222   std::size_t size;
00223   if (not (stream >> size))
00224     throw calc_error("malformed library file, cannot read function");
00225   parameters_.reserve(size);
00226   while (size-- != 0) {
00227     std::string parameter;
00228     if (not (stream >> parameter))
00229       throw calc_error("malformed library file, cannot read function parameter");
00230     parameters_.push_back(parameter);
00231   }
00232   definition_ = node(stream);
00233 }
00234 
00235 identifier_list const& node_function::parameters()
00236 const
00237 {
00238   return parameters_;
00239 }
00240 
00241 node node_function::definition()
00242 const
00243 {
00244   return definition_;
00245 }
00246 
00247 void print_identifier_list(std::ostream& stream, identifier_list const& identifiers)
00248 {
00249   stream << '(';
00250   char const* sep = "";
00251   for (identifier_list::const_iterator id(identifiers.begin()); id != identifiers.end(); ++id) {
00252     stream << sep << *id;
00253     sep = ", ";
00254   }
00255   stream << ')';
00256 }
00257 
00258 void node_function::print_node(std::ostream& stream, int indent)
00259 const
00260 {
00261   stream << std::setw(indent) << "" << "fun\n";
00262   print_identifier_list(stream, parameters());
00263   stream << '=';
00264   definition().print(stream, indent + 2);
00265 }
00266 
00267 double node_function::evaluate_node()
00268 const
00269 {
00270   return definition().evaluate();
00271 }
00272 
00273 identifier_list const& node_function::evaluate_parameters()
00274 const
00275 {
00276   return parameters();
00277 }
00278 
00279 void node_function::save_node(std::ostream& stream)
00280 const
00281 {
00282   stream << "function " << parameters().size() << ' ';
00283   std::copy(parameters().begin(), parameters().end(), std::ostream_iterator<std::string>(stream, " "));
00284   definition().save(stream);
00285 }
00286 
00287 
00288 node_function_call::node_function_call(std::string const& name, node_list const& arguments)
00289 : node_impl(), name_(name), arguments_(arguments)
00290 {}
00291 
00292 node_function_call::node_function_call(std::istream& stream)
00293 : node_impl()
00294 {
00295   std::string name;
00296   if (not (stream >> name_))
00297     throw calc_error("malformed library file, cannot read function call name");
00298   std::size_t size;
00299   if (not (stream >> size))
00300     throw calc_error("malformed library file, cannot read function call");
00301   arguments_.reserve(size);
00302   while (size-- != 0) {
00303     arguments_.push_back(node(stream));
00304   }
00305 }
00306 
00307 std::string node_function_call::name()
00308 const
00309 {
00310   return name_;
00311 }
00312 
00313 node_list const& node_function_call::arguments()
00314 const
00315 {
00316   return arguments_;
00317 }
00318 
00319 void node_function_call::print_node(std::ostream& stream, int indent)
00320 const
00321 {
00322   stream << std::setw(indent) << "" << name() << "(\n";
00323   for (node_list::const_iterator first(arguments().begin()), arg(first); arg != arguments().end(); ++arg) {
00324     stream << std::setw(indent+1) << "" << "arg " << std::distance(first, arg) << ": ";
00325     arg->print(stream, indent + 2);
00326   }
00327   stream << std::setw(indent) << "" << ")\n";
00328 }
00329 
00330 double node_function_call::evaluate_node()
00331 const
00332 {
00333   // Create a local symbol table, assigning all the node values to the parameters.
00334   node function = get_function(name());
00335   identifier_list const& parameters( function.get_parameters() );
00336   if (parameters.size() != arguments().size())
00337     throw function_error(name(), parameters.size(), arguments().size());
00338   else
00339   {
00340     // Create a local symbol table by assigning the arguments to the function parameters.
00341     symbol_table locals;
00342     identifier_list::const_iterator parm(parameters.begin());
00343     for (node_list::const_iterator arg(arguments().begin()); arg != arguments().end(); ++arg, ++parm) {
00344       locals.insert(std::make_pair(*parm, *arg));
00345     }
00346     set_symbol_table syms(locals);
00347     return function.evaluate();
00348   }
00349 }
00350 
00351 void node_function_call::save_node(std::ostream& stream)
00352 const
00353 {
00354   stream << "call " << name() << ' ' << arguments().size() << ' ';
00355   for (node_list::const_iterator arg(arguments().begin()); arg != arguments().end(); ++arg)
00356     arg->save(stream);
00357 }
00358 
00359 
00360 node_unary::node_unary(node operand)
00361 : node_impl(), operand_(operand)
00362 {}
00363 
00364 node_unary::node_unary(std::istream& stream)
00365 : node_impl(), operand_(stream)
00366 {}
00367 
00368 node node_unary::operand()
00369 const
00370 {
00371   return operand_;
00372 }
00373 
00374 double node_unary::evaluate_operand()
00375 const
00376 {
00377   return operand().evaluate();
00378 }
00379 
00380 node_binary::node_binary(node left, node right)
00381 : left_(left), right_(right)
00382 {}
00383 
00384 node_binary::node_binary(std::istream& stream)
00385 : node_impl(), left_(stream), right_(stream)
00386 {}
00387 
00388 node node_binary::left()
00389 const
00390 {
00391   return left_;
00392 }
00393 
00394 node node_binary::right()
00395 const
00396 {
00397   return right_;
00398 }
00399 
00400 double node_binary::evaluate_left()
00401 const
00402 {
00403   return left().evaluate();
00404 }
00405 
00406 double node_binary::evaluate_right()
00407 const
00408 {
00409   return right().evaluate();
00410 }
00411 
00412 
00413 node_negate::node_negate(node operand)
00414 : node_unary(operand)
00415 {}
00416 
00417 node_negate::node_negate(std::istream& stream)
00418 : node_unary(stream)
00419 {}
00420 
00421 void node_negate::print_node(std::ostream& stream, int indent)
00422 const
00423 {
00424   stream << std::setw(indent) << "" << "-\n";
00425   operand().print(stream, indent + 2);
00426 }
00427 
00428 double node_negate::evaluate_node()
00429 const
00430 {
00431   return -evaluate_operand();
00432 }
00433 
00434 void node_negate::save_node(std::ostream& stream)
00435 const
00436 {
00437   stream << "negate ";
00438   operand().save(stream);
00439 }
00440 
00441 
00442 
00443 node_add::node_add(node left, node right)
00444 : node_binary(left, right)
00445 {}
00446 
00447 node_add::node_add(std::istream& stream)
00448 : node_binary(stream)
00449 {}
00450 
00451 void node_add::print_node(std::ostream& stream, int indent)
00452 const
00453 {
00454   stream << std::setw(indent) << "" << "+\n";
00455   left().print(stream, indent + 2);
00456   right().print(stream, indent + 2);
00457 }
00458 
00459 double node_add::evaluate_node()
00460 const
00461 {
00462   return evaluate_left() + evaluate_right();
00463 }
00464 
00465 void node_add::save_node(std::ostream& stream)
00466 const
00467 {
00468   stream << "add ";
00469   left().save(stream);
00470   right().save(stream);
00471 }
00472 
00473 
00474 node_subtract::node_subtract(node left, node right)
00475 : node_binary(left, right)
00476 {}
00477 
00478 node_subtract::node_subtract(std::istream& stream)
00479 : node_binary(stream)
00480 {}
00481 
00482 void node_subtract::print_node(std::ostream& stream, int indent)
00483 const
00484 {
00485   stream << std::setw(indent) << "" << "-\n";
00486   left().print(stream, indent + 2);
00487   right().print(stream, indent + 2);
00488 }
00489 
00490 double node_subtract::evaluate_node()
00491 const
00492 {
00493   return evaluate_left() - evaluate_right();
00494 }
00495 
00496 void node_subtract::save_node(std::ostream& stream)
00497 const
00498 {
00499   stream << "subtract ";
00500   left().save(stream);
00501   right().save(stream);
00502 }
00503 
00504 
00505 node_multiply::node_multiply(node left, node right)
00506 : node_binary(left, right)
00507 {}
00508 
00509 node_multiply::node_multiply(std::istream& stream)
00510 : node_binary(stream)
00511 {}
00512 
00513 void node_multiply::print_node(std::ostream& stream, int indent)
00514 const
00515 {
00516   stream << std::setw(indent) << "" << "*\n";
00517   left().print(stream, indent + 2);
00518   right().print(stream, indent + 2);
00519 }
00520 
00521 double node_multiply::evaluate_node()
00522 const
00523 {
00524   return evaluate_left() * evaluate_right();
00525 }
00526 
00527 void node_multiply::save_node(std::ostream& stream)
00528 const
00529 {
00530   stream << "multiply ";
00531   left().save(stream);
00532   right().save(stream);
00533 }
00534 
00535 
00536 node_divide::node_divide(node left, node right)
00537 : node_binary(left, right)
00538 {}
00539 
00540 node_divide::node_divide(std::istream& stream)
00541 : node_binary(stream)
00542 {}
00543 
00544 void node_divide::print_node(std::ostream& stream, int indent)
00545 const
00546 {
00547   stream << std::setw(indent) << "" << "/\n";
00548   left().print(stream, indent + 2);
00549   right().print(stream, indent + 2);
00550 }
00551 
00552 double node_divide::evaluate_node()
00553 const
00554 {
00555   return evaluate_left() / evaluate_right();
00556 }
00557 
00558 void node_divide::save_node(std::ostream& stream)
00559 const
00560 {
00561   stream << "divide ";
00562   left().save(stream);
00563   right().save(stream);
00564 }

Generated on Sun Nov 30 10:05:49 2008 for Calculator by  doxygen 1.5.3