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 number 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 number node_void::evaluate_node()
00120 const
00121 {
00122   return number();
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(number value)
00138 : node_impl(), value_(value)
00139 {}
00140 
00141 node_number::node_number(std::istream& stream)
00142 : node_impl(), value_(stream)
00143 {}
00144 
00145 number node_number::value()
00146 const
00147 {
00148   return value_;
00149 }
00150 
00151 void node_number::print_node(std::ostream& stream, int indent)
00152 const
00153 {
00154   stream << std::setw(indent) << "" << value() << '\n';
00155 }
00156 
00157 number node_number::evaluate_node()
00158 const
00159 {
00160   return value();
00161 }
00162 
00163 void node_number::save_node(std::ostream& stream)
00164 const
00165 {
00166   stream << "number ";
00167   value().save(stream);
00168   stream << '\n';
00169 }
00170 
00171 
00172 node_identifier::node_identifier(std::string const& name)
00173 : node_impl(), name_(name)
00174 {}
00175 
00176 node_identifier::node_identifier(std::istream& stream)
00177 : node_impl()
00178 {
00179   if (not (stream >> name_))
00180     throw calc_error("malformed library file, cannot read identifier");
00181 }
00182 
00183 std::string const& node_identifier::name()
00184 const
00185 {
00186   return name_;
00187 }
00188 
00189 void node_identifier::print_node(std::ostream& stream, int indent)
00190 const
00191 {
00192   stream << std::setw(indent) << "" << "identifier " << name() << '\n';
00193 }
00194 
00195 number node_identifier::evaluate_node()
00196 const
00197 {
00198   return get_variable(name()).evaluate();
00199 }
00200 
00201 std::string node_identifier::evaluate_string()
00202 const
00203 {
00204   return name();
00205 }
00206 
00207 void node_identifier::save_node(std::ostream& stream)
00208 const
00209 {
00210   stream << "identifier " << name() << '\n';
00211 }
00212 
00213 
00214 node_function::node_function(identifier_list const& parameters, node definition)
00215 : node_impl(), parameters_(parameters), definition_(definition)
00216 {}
00217 
00218 node_function::node_function(std::istream& stream)
00219 : node_impl()
00220 {
00221   std::size_t size;
00222   if (not (stream >> size))
00223     throw calc_error("malformed library file, cannot read function");
00224   parameters_.reserve(size);
00225   while (size-- != 0) {
00226     std::string parameter;
00227     if (not (stream >> parameter))
00228       throw calc_error("malformed library file, cannot read function parameter");
00229     parameters_.push_back(parameter);
00230   }
00231   definition_ = node(stream);
00232 }
00233 
00234 identifier_list const& node_function::parameters()
00235 const
00236 {
00237   return parameters_;
00238 }
00239 
00240 node node_function::definition()
00241 const
00242 {
00243   return definition_;
00244 }
00245 
00246 void print_identifier_list(std::ostream& stream, identifier_list const& identifiers)
00247 {
00248   stream << '(';
00249   char const* sep = "";
00250   for (identifier_list::const_iterator id(identifiers.begin()); id != identifiers.end(); ++id) {
00251     stream << sep << *id;
00252     sep = ", ";
00253   }
00254   stream << ')';
00255 }
00256 
00257 void node_function::print_node(std::ostream& stream, int indent)
00258 const
00259 {
00260   stream << std::setw(indent) << "" << "fun\n";
00261   print_identifier_list(stream, parameters());
00262   stream << '=';
00263   definition().print(stream, indent + 2);
00264 }
00265 
00266 number node_function::evaluate_node()
00267 const
00268 {
00269   return definition().evaluate();
00270 }
00271 
00272 identifier_list const& node_function::evaluate_parameters()
00273 const
00274 {
00275   return parameters();
00276 }
00277 
00278 void node_function::save_node(std::ostream& stream)
00279 const
00280 {
00281   stream << "function " << parameters().size() << ' ';
00282   std::copy(parameters().begin(), parameters().end(), std::ostream_iterator<std::string>(stream, " "));
00283   definition().save(stream);
00284 }
00285 
00286 
00287 node_function_call::node_function_call(std::string const& name, node_list const& arguments)
00288 : node_impl(), name_(name), arguments_(arguments)
00289 {}
00290 
00291 node_function_call::node_function_call(std::istream& stream)
00292 : node_impl()
00293 {
00294   std::string name;
00295   if (not (stream >> name_))
00296     throw calc_error("malformed library file, cannot read function call name");
00297   std::size_t size;
00298   if (not (stream >> size))
00299     throw calc_error("malformed library file, cannot read function call");
00300   arguments_.reserve(size);
00301   while (size-- != 0) {
00302     arguments_.push_back(node(stream));
00303   }
00304 }
00305 
00306 std::string node_function_call::name()
00307 const
00308 {
00309   return name_;
00310 }
00311 
00312 node_list const& node_function_call::arguments()
00313 const
00314 {
00315   return arguments_;
00316 }
00317 
00318 void node_function_call::print_node(std::ostream& stream, int indent)
00319 const
00320 {
00321   stream << std::setw(indent) << "" << name() << "(\n";
00322   for (node_list::const_iterator first(arguments().begin()), arg(first); arg != arguments().end(); ++arg) {
00323     stream << std::setw(indent+1) << "" << "arg " << std::distance(first, arg) << ": ";
00324     arg->print(stream, indent + 2);
00325   }
00326   stream << std::setw(indent) << "" << ")\n";
00327 }
00328 
00329 number node_function_call::evaluate_node()
00330 const
00331 {
00332   // Create a local symbol table, assigning all the node values to the parameters.
00333   node function = get_function(name());
00334   identifier_list const& parameters( function.get_parameters() );
00335   if (parameters.size() != arguments().size())
00336     throw function_error(name(), parameters.size(), arguments().size());
00337   else
00338   {
00339     // Create a local symbol table by assigning the arguments to the function parameters.
00340     symbol_table locals;
00341     identifier_list::const_iterator parm(parameters.begin());
00342     for (node_list::const_iterator arg(arguments().begin()); arg != arguments().end(); ++arg, ++parm) {
00343       locals.insert(std::make_pair(*parm, *arg));
00344     }
00345     set_symbol_table syms(locals);
00346     return function.evaluate();
00347   }
00348 }
00349 
00350 void node_function_call::save_node(std::ostream& stream)
00351 const
00352 {
00353   stream << "call " << name() << ' ' << arguments().size() << ' ';
00354   for (node_list::const_iterator arg(arguments().begin()); arg != arguments().end(); ++arg)
00355     arg->save(stream);
00356 }
00357 
00358 
00359 node_unary::node_unary(node operand)
00360 : node_impl(), operand_(operand)
00361 {}
00362 
00363 node_unary::node_unary(std::istream& stream)
00364 : node_impl(), operand_(stream)
00365 {}
00366 
00367 node node_unary::operand()
00368 const
00369 {
00370   return operand_;
00371 }
00372 
00373 number node_unary::evaluate_operand()
00374 const
00375 {
00376   return operand().evaluate();
00377 }
00378 
00379 node_binary::node_binary(node left, node right)
00380 : left_(left), right_(right)
00381 {}
00382 
00383 node_binary::node_binary(std::istream& stream)
00384 : node_impl(), left_(stream), right_(stream)
00385 {}
00386 
00387 node node_binary::left()
00388 const
00389 {
00390   return left_;
00391 }
00392 
00393 node node_binary::right()
00394 const
00395 {
00396   return right_;
00397 }
00398 
00399 number node_binary::evaluate_left()
00400 const
00401 {
00402   return left().evaluate();
00403 }
00404 
00405 number node_binary::evaluate_right()
00406 const
00407 {
00408   return right().evaluate();
00409 }
00410 
00411 
00412 node_negate::node_negate(node operand)
00413 : node_unary(operand)
00414 {}
00415 
00416 node_negate::node_negate(std::istream& stream)
00417 : node_unary(stream)
00418 {}
00419 
00420 void node_negate::print_node(std::ostream& stream, int indent)
00421 const
00422 {
00423   stream << std::setw(indent) << "" << "-\n";
00424   operand().print(stream, indent + 2);
00425 }
00426 
00427 number node_negate::evaluate_node()
00428 const
00429 {
00430   return -evaluate_operand();
00431 }
00432 
00433 void node_negate::save_node(std::ostream& stream)
00434 const
00435 {
00436   stream << "negate ";
00437   operand().save(stream);
00438 }
00439 
00440 
00441 
00442 node_add::node_add(node left, node right)
00443 : node_binary(left, right)
00444 {}
00445 
00446 node_add::node_add(std::istream& stream)
00447 : node_binary(stream)
00448 {}
00449 
00450 void node_add::print_node(std::ostream& stream, int indent)
00451 const
00452 {
00453   stream << std::setw(indent) << "" << "+\n";
00454   left().print(stream, indent + 2);
00455   right().print(stream, indent + 2);
00456 }
00457 
00458 number node_add::evaluate_node()
00459 const
00460 {
00461   return evaluate_left() + evaluate_right();
00462 }
00463 
00464 void node_add::save_node(std::ostream& stream)
00465 const
00466 {
00467   stream << "add ";
00468   left().save(stream);
00469   right().save(stream);
00470 }
00471 
00472 
00473 node_subtract::node_subtract(node left, node right)
00474 : node_binary(left, right)
00475 {}
00476 
00477 node_subtract::node_subtract(std::istream& stream)
00478 : node_binary(stream)
00479 {}
00480 
00481 void node_subtract::print_node(std::ostream& stream, int indent)
00482 const
00483 {
00484   stream << std::setw(indent) << "" << "-\n";
00485   left().print(stream, indent + 2);
00486   right().print(stream, indent + 2);
00487 }
00488 
00489 number node_subtract::evaluate_node()
00490 const
00491 {
00492   return evaluate_left() - evaluate_right();
00493 }
00494 
00495 void node_subtract::save_node(std::ostream& stream)
00496 const
00497 {
00498   stream << "subtract ";
00499   left().save(stream);
00500   right().save(stream);
00501 }
00502 
00503 
00504 node_multiply::node_multiply(node left, node right)
00505 : node_binary(left, right)
00506 {}
00507 
00508 node_multiply::node_multiply(std::istream& stream)
00509 : node_binary(stream)
00510 {}
00511 
00512 void node_multiply::print_node(std::ostream& stream, int indent)
00513 const
00514 {
00515   stream << std::setw(indent) << "" << "*\n";
00516   left().print(stream, indent + 2);
00517   right().print(stream, indent + 2);
00518 }
00519 
00520 number node_multiply::evaluate_node()
00521 const
00522 {
00523   return evaluate_left() * evaluate_right();
00524 }
00525 
00526 void node_multiply::save_node(std::ostream& stream)
00527 const
00528 {
00529   stream << "multiply ";
00530   left().save(stream);
00531   right().save(stream);
00532 }
00533 
00534 
00535 node_divide::node_divide(node left, node right)
00536 : node_binary(left, right)
00537 {}
00538 
00539 node_divide::node_divide(std::istream& stream)
00540 : node_binary(stream)
00541 {}
00542 
00543 void node_divide::print_node(std::ostream& stream, int indent)
00544 const
00545 {
00546   stream << std::setw(indent) << "" << "/\n";
00547   left().print(stream, indent + 2);
00548   right().print(stream, indent + 2);
00549 }
00550 
00551 number node_divide::evaluate_node()
00552 const
00553 {
00554   return evaluate_left() / evaluate_right();
00555 }
00556 
00557 void node_divide::save_node(std::ostream& stream)
00558 const
00559 {
00560   stream << "divide ";
00561   left().save(stream);
00562   right().save(stream);
00563 }

Generated on Sun Nov 30 10:06:52 2008 for Calculator by  doxygen 1.5.3