Calculator  Step 5
node_impl.cpp
Go to the documentation of this file.
1 #include <iomanip>
2 #include <iterator>
3 #include <ostream>
4 #include <sstream>
5 #include <utility>
6 
7 #include "calc_error.hpp"
8 #include "node.hpp"
9 #include "node_impl.hpp"
10 #include "variables.hpp"
11 
13 {}
14 
16 {}
17 
18 void node_impl::print(std::ostream& stream, int indent)
19 const
20 {
21  print_node(stream, indent);
22 }
23 
25 const
26 {
27  return evaluate_node();
28 }
29 
30 std::string node_impl::to_string()
31 const
32 {
33  return evaluate_string();
34 }
35 
37 const
38 {
39  return evaluate_parameters();
40 }
41 
43 const
44 {
45  std::ostringstream stream{};
46  stream << evaluate();
47  return stream.str();
48 }
49 
51 const
52 {
53  static identifier_list const empty{};
54  return empty;
55 }
56 
57 void node_impl::save(std::ostream& stream)
58 const
59 {
60  save_node(stream);
61 }
62 
63 /* Factory function to create node_impl objects from a saved library file. */
64 std::shared_ptr<node_impl> node_impl::read_node(std::istream& stream)
65 {
66  std::string type{};
67  if (not (stream >> type))
68  return nullptr;
69  if (type == "void")
70  return std::make_shared<node_void>(stream);
71  if (type == "number")
72  return std::make_shared<node_number>(stream);
73  if (type == "identifier")
74  return std::make_shared<node_identifier>(stream);
75  if (type == "function")
76  return std::make_shared<node_function>(stream);
77  if (type == "call")
78  return std::make_shared<node_function_call>(stream);
79  if (type == "negate")
80  return std::make_shared<node_negate>(stream);
81  if (type == "add")
82  return std::make_shared<node_add>(stream);
83  if (type == "subtract")
84  return std::make_shared<node_subtract>(stream);
85  if (type == "multiply")
86  return std::make_shared<node_multiply>(stream);
87  if (type == "divide")
88  return std::make_shared<node_divide>(stream);
89 
90  throw calc_error{"unknown node type: " + type};
91 }
92 
94 : node_impl{}
95 {}
96 
97 node_void::node_void(std::istream&)
98 : node_impl{}
99 {}
100 
101 void node_void::print_node(std::ostream& stream, int indent)
102 const
103 {
104  stream << std::setw(indent) << "" << "void\n";
105 }
106 
108 const
109 {
110  return 0.0;
111 }
112 
114 const
115 {
116  return std::string{};
117 }
118 
119 void node_void::save_node(std::ostream& stream)
120 const
121 {
122  stream << "void\n";
123 }
124 
126 : node_impl{}, value_{value}
127 {}
128 
129 node_number::node_number(std::istream& stream)
130 : node_impl{}
131 {
132  if (not (stream >> value_))
133  throw calc_error{"malformed library file, cannot read number"};
134 }
135 
137 const
138 {
139  return value_;
140 }
141 
142 void node_number::print_node(std::ostream& stream, int indent)
143 const
144 {
145  stream << std::setw(indent) << "" << value() << '\n';
146 }
147 
149 const
150 {
151  return value();
152 }
153 
154 void node_number::save_node(std::ostream& stream)
155 const
156 {
157  stream << "number " << value() << '\n';
158 }
159 
160 
162 : node_impl{}, name_{std::move(name)}
163 {}
164 
165 node_identifier::node_identifier(std::istream& stream)
166 : node_impl{}
167 {
168  if (not (stream >> name_))
169  throw calc_error{"malformed library file, cannot read identifier"};
170 }
171 
172 std::string const& node_identifier::name()
173 const
174 {
175  return name_;
176 }
177 
178 void node_identifier::print_node(std::ostream& stream, int indent)
179 const
180 {
181  stream << std::setw(indent) << "" << "identifier " << name() << '\n';
182 }
183 
185 const
186 {
187  return get_variable(name()).evaluate();
188 }
189 
191 const
192 {
193  return name();
194 }
195 
196 void node_identifier::save_node(std::ostream& stream)
197 const
198 {
199  stream << "identifier " << name() << '\n';
200 }
201 
202 
204 : node_impl{}, parameters_{std::move(parameters)}, definition_(definition)
205 {}
206 
207 node_function::node_function(std::istream& stream)
208 : node_impl{}
209 {
210  std::size_t size{};
211  if (not (stream >> size))
212  throw calc_error{"malformed library file, cannot read function"};
213  parameters_.reserve(size);
214  while (size-- != 0) {
215  std::string parameter{};
216  if (not (stream >> parameter))
217  throw calc_error{"malformed library file, cannot read function parameter"};
218  parameters_.emplace_back(std::move(parameter));
219  }
220  definition_ = node(stream);
221 }
222 
224 const
225 {
226  return parameters_;
227 }
228 
230 const
231 {
232  return definition_;
233 }
234 
235 void print_identifier_list(std::ostream& stream, identifier_list const& identifiers)
236 {
237  stream << '(';
238  char const* sep = "";
239  for (auto const& id : identifiers) {
240  stream << sep << id;
241  sep = ", ";
242  }
243  stream << ')';
244 }
245 
246 void node_function::print_node(std::ostream& stream, int indent)
247 const
248 {
249  stream << std::setw(indent) << "" << "fun\n";
251  stream << '=';
252  definition().print(stream, indent + 2);
253 }
254 
256 const
257 {
258  return definition().evaluate();
259 }
260 
262 const
263 {
264  return parameters();
265 }
266 
267 void node_function::save_node(std::ostream& stream)
268 const
269 {
270  stream << "function " << parameters().size() << ' ';
271  for (auto const& parameter : parameters())
272  stream << parameter << ' ';
273  definition().save(stream);
274 }
275 
276 
278 : node_impl{}, name_{std::move(name)}, arguments_{std::move(arguments)}
279 {}
280 
282 : node_impl{}
283 {
284  std::string name{};
285  if (not (stream >> name_))
286  throw calc_error{"malformed library file, cannot read function call name"};
287  std::size_t size{};
288  if (not (stream >> size))
289  throw calc_error{"malformed library file, cannot read function call"};
290  arguments_.reserve(size);
291  while (size-- != 0) {
292  arguments_.emplace_back(stream);
293  }
294 }
295 
297 const
298 {
299  return name_;
300 }
301 
303 const
304 {
305  return arguments_;
306 }
307 
308 void node_function_call::print_node(std::ostream& stream, int indent)
309 const
310 {
311  stream << std::setw(indent) << "" << name() << "(\n";
312  std::size_t index{0};
313  for (auto const& arg : arguments()) {
314  stream << std::setw(indent+1) << "" << "arg " << index << ": ";
315  arg.print(stream, indent + 2);
316  ++index;
317  }
318  stream << std::setw(indent) << "" << ")\n";
319 }
320 
322 const
323 {
324  // Create a local symbol table, assigning all the node values to the parameters.
325  node function{ get_function(name()) };
326  identifier_list const& parameters{ function.get_parameters() };
327  if (parameters.size() != arguments().size())
328  throw function_error{name(), parameters.size(), arguments().size()};
329  else
330  {
331  // Create a local symbol table by assigning the arguments to the function parameters.
332  symbol_table locals{};
333  identifier_list::const_iterator parm{parameters.begin()};
334  for (auto const& arg : arguments()) {
335  locals.emplace(*parm, arg);
336  ++parm;
337  }
338  set_symbol_table syms{locals};
339  return function.evaluate();
340  }
341 }
342 
343 void node_function_call::save_node(std::ostream& stream)
344 const
345 {
346  stream << "call " << name() << ' ' << arguments().size() << ' ';
347  for (auto const& arg : arguments())
348  arg.save(stream);
349 }
350 
351 
353 : node_impl{}, operand_{operand}
354 {}
355 
356 node_unary::node_unary(std::istream& stream)
357 : node_impl{}, operand_{stream}
358 {}
359 
361 const
362 {
363  return operand_;
364 }
365 
367 const
368 {
369  return operand().evaluate();
370 }
371 
373 : node_impl{}, left_{left}, right_{right}
374 {}
375 
376 node_binary::node_binary(std::istream& stream)
377 : node_impl{}, left_{stream}, right_{stream}
378 {}
379 
381 const
382 {
383  return left_;
384 }
385 
387 const
388 {
389  return right_;
390 }
391 
393 const
394 {
395  return left().evaluate();
396 }
397 
399 const
400 {
401  return right().evaluate();
402 }
403 
404 
406 : node_unary{operand}
407 {}
408 
409 node_negate::node_negate(std::istream& stream)
410 : node_unary{stream}
411 {}
412 
413 void node_negate::print_node(std::ostream& stream, int indent)
414 const
415 {
416  stream << std::setw(indent) << "" << "-\n";
417  operand().print(stream, indent + 2);
418 }
419 
421 const
422 {
423  return -evaluate_operand();
424 }
425 
426 void node_negate::save_node(std::ostream& stream)
427 const
428 {
429  stream << "negate ";
430  operand().save(stream);
431 }
432 
433 
434 
436 : node_binary{left, right}
437 {}
438 
439 node_add::node_add(std::istream& stream)
440 : node_binary{stream}
441 {}
442 
443 void node_add::print_node(std::ostream& stream, int indent)
444 const
445 {
446  stream << std::setw(indent) << "" << "+\n";
447  left().print(stream, indent + 2);
448  right().print(stream, indent + 2);
449 }
450 
452 const
453 {
454  return evaluate_left() + evaluate_right();
455 }
456 
457 void node_add::save_node(std::ostream& stream)
458 const
459 {
460  stream << "add ";
461  left().save(stream);
462  right().save(stream);
463 }
464 
465 
467 : node_binary{left, right}
468 {}
469 
470 node_subtract::node_subtract(std::istream& stream)
471 : node_binary{stream}
472 {}
473 
474 void node_subtract::print_node(std::ostream& stream, int indent)
475 const
476 {
477  stream << std::setw(indent) << "" << "-\n";
478  left().print(stream, indent + 2);
479  right().print(stream, indent + 2);
480 }
481 
483 const
484 {
485  return evaluate_left() - evaluate_right();
486 }
487 
488 void node_subtract::save_node(std::ostream& stream)
489 const
490 {
491  stream << "subtract ";
492  left().save(stream);
493  right().save(stream);
494 }
495 
496 
498 : node_binary{left, right}
499 {}
500 
501 node_multiply::node_multiply(std::istream& stream)
502 : node_binary{stream}
503 {}
504 
505 void node_multiply::print_node(std::ostream& stream, int indent)
506 const
507 {
508  stream << std::setw(indent) << "" << "*\n";
509  left().print(stream, indent + 2);
510  right().print(stream, indent + 2);
511 }
512 
514 const
515 {
516  return evaluate_left() * evaluate_right();
517 }
518 
519 void node_multiply::save_node(std::ostream& stream)
520 const
521 {
522  stream << "multiply ";
523  left().save(stream);
524  right().save(stream);
525 }
526 
527 
529 : node_binary{left, right}
530 {}
531 
532 node_divide::node_divide(std::istream& stream)
533 : node_binary{stream}
534 {}
535 
536 void node_divide::print_node(std::ostream& stream, int indent)
537 const
538 {
539  stream << std::setw(indent) << "" << "/\n";
540  left().print(stream, indent + 2);
541  right().print(stream, indent + 2);
542 }
543 
545 const
546 {
547  return evaluate_left() / evaluate_right();
548 }
549 
550 void node_divide::save_node(std::ostream& stream)
551 const
552 {
553  stream << "divide ";
554  left().save(stream);
555  right().save(stream);
556 }
virtual double evaluate_node() const override
Definition: node_impl.cpp:184
node_number(double value)
Definition: node_impl.cpp:125
std::string name_
Definition: node_impl.hpp:92
double evaluate_right() const
Definition: node_impl.cpp:398
node get_function(std::string const &name)
Definition: variables.cpp:65
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:457
void save(std::ostream &stream) const
Definition: node_impl.cpp:57
node_unary(node operand)
Definition: node_impl.cpp:352
std::string name() const
Definition: node_impl.cpp:296
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:488
virtual std::string evaluate_string() const override
Definition: node_impl.cpp:113
virtual std::string evaluate_string() const
Definition: node_impl.cpp:42
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:178
virtual double evaluate_node() const =0
virtual double evaluate_node() const override
Definition: node_impl.cpp:255
node_list const & arguments() const
Definition: node_impl.cpp:302
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:536
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:474
double evaluate_left() const
Definition: node_impl.cpp:392
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:154
node_function_call(std::string name, node_list arguments)
Definition: node_impl.cpp:277
double value_
Definition: node_impl.hpp:75
node_binary(node left, node right)
Definition: node_impl.cpp:372
Definition: node.hpp:26
virtual double evaluate_node() const override
Definition: node_impl.cpp:482
virtual double evaluate_node() const override
Definition: node_impl.cpp:513
std::string const & name() const
Definition: node_impl.cpp:172
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:101
virtual std::string evaluate_string() const override
Definition: node_impl.cpp:190
node_identifier(std::string name)
Definition: node_impl.cpp:161
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:519
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:246
virtual double evaluate_node() const override
Definition: node_impl.cpp:321
virtual double evaluate_node() const override
Definition: node_impl.cpp:148
void print(std::ostream &stream, int indent) const
Definition: node_impl.cpp:18
node operand_
Definition: node_impl.hpp:143
std::vector< std::string > identifier_list
A sequence of identifiers (e.g., parameter names).
Definition: node.hpp:19
static std::shared_ptr< node_impl > read_node(std::istream &stream)
Definition: node_impl.cpp:64
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:142
virtual ~node_impl()
Definition: node_impl.cpp:15
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:196
node right() const
Definition: node_impl.cpp:386
node_function(identifier_list parameters, node definition)
Definition: node_impl.cpp:203
double evaluate_operand() const
Definition: node_impl.cpp:366
node definition() const
Definition: node_impl.cpp:229
node_multiply(node left, node right)
Definition: node_impl.cpp:497
virtual identifier_list const & evaluate_parameters() const override
Definition: node_impl.cpp:261
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:308
void print(std::ostream &stream, int indent=0) const
Definition: node.cpp:54
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:119
void print_identifier_list(std::ostream &stream, identifier_list const &identifiers)
Definition: node_impl.cpp:235
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:413
node_list arguments_
Definition: node_impl.hpp:127
virtual void print_node(std::ostream &stream, int indent) const =0
identifier_list parameters_
Definition: node_impl.hpp:110
node_subtract(node left, node right)
Definition: node_impl.cpp:466
double evaluate() const
Definition: node_impl.cpp:24
virtual void save_node(std::ostream &stream) const =0
virtual double evaluate_node() const override
Definition: node_impl.cpp:107
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:443
double evaluate() const
Definition: node.cpp:60
virtual identifier_list const & evaluate_parameters() const
Definition: node_impl.cpp:50
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:267
virtual double evaluate_node() const override
Definition: node_impl.cpp:544
identifier_list const & get_parameters() const
Definition: node.cpp:72
identifier_list const & get_parameters() const
Definition: node_impl.cpp:36
double value() const
Definition: node_impl.cpp:136
std::vector< node > node_list
A sequence of nodes.
Definition: node.hpp:13
std::string name_
Definition: node_impl.hpp:126
std::string to_string() const
Definition: node_impl.cpp:30
node operand() const
Definition: node_impl.cpp:360
void save(std::ostream &stream) const
Definition: node.cpp:78
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:426
node_negate(node operand)
Definition: node_impl.cpp:405
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:505
virtual double evaluate_node() const override
Definition: node_impl.cpp:451
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:550
node_divide(node left, node right)
Definition: node_impl.cpp:528
node_add(node left, node right)
Definition: node_impl.cpp:435
node left() const
Definition: node_impl.cpp:380
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:343
identifier_list const & parameters() const
Definition: node_impl.cpp:223
node get_variable(std::string const &name)
Definition: variables.cpp:49
std::map< std::string, node > symbol_table
Definition: variables.hpp:13
virtual double evaluate_node() const override
Definition: node_impl.cpp:420