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