Calculator Step 5

- Main Page
- Classes
- Files

- File List
- File Members

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
12 node_impl::node_impl()
13 {}
14
15 node_impl::~node_impl()
16 {}
17
18 void node_impl::print(std::ostream& stream, int indent)
19 const
20 {
21 print_node(stream, indent);
22 }
23
24 double node_impl::evaluate()
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
36 identifier_list const& node_impl::get_parameters()
37 const
38 {
39 return evaluate_parameters();
40 }
41
42 std::string node_impl::evaluate_string()
43 const
44 {
45 std::ostringstream stream{};
46 stream << evaluate();
47 return stream.str();
48 }
49
50 identifier_list const& node_impl::evaluate_parameters()
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
93 node_void::node_void()
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
107 double node_void::evaluate_node()
108 const
109 {
110 return 0.0;
111 }
112
113 std::string node_void::evaluate_string()
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
125 node_number::node_number(double value)
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
136 double node_number::value()
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
148 double node_number::evaluate_node()
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
161 node_identifier::node_identifier(std::string name)
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
184 double node_identifier::evaluate_node()
185 const
186 {
187 return get_variable(name()).evaluate();
188 }
189
190 std::string node_identifier::evaluate_string()
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
203 node_function::node_function(identifier_list parameters, node definition)
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
223 identifier_list const& node_function::parameters()
224 const
225 {
226 return parameters_;
227 }
228
229 node node_function::definition()
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";
250 print_identifier_list(stream, parameters());
251 stream << '=';
252 definition().print(stream, indent + 2);
253 }
254
255 double node_function::evaluate_node()
256 const
257 {
258 return definition().evaluate();
259 }
260
261 identifier_list const& node_function::evaluate_parameters()
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
277 node_function_call::node_function_call(std::string name, node_list arguments)
278 : node_impl{}, name_{std::move(name)}, arguments_{std::move(arguments)}
279 {}
280
281 node_function_call::node_function_call(std::istream& stream)
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
296 std::string node_function_call::name()
297 const
298 {
299 return name_;
300 }
301
302 node_list const& node_function_call::arguments()
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
321 double node_function_call::evaluate_node()
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
352 node_unary::node_unary(node operand)
353 : node_impl{}, operand_{operand}
354 {}
355
356 node_unary::node_unary(std::istream& stream)
357 : node_impl{}, operand_{stream}
358 {}
359
360 node node_unary::operand()
361 const
362 {
363 return operand_;
364 }
365
366 double node_unary::evaluate_operand()
367 const
368 {
369 return operand().evaluate();
370 }
371
372 node_binary::node_binary(node left, node right)
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
380 node node_binary::left()
381 const
382 {
383 return left_;
384 }
385
386 node node_binary::right()
387 const
388 {
389 return right_;
390 }
391
392 double node_binary::evaluate_left()
393 const
394 {
395 return left().evaluate();
396 }
397
398 double node_binary::evaluate_right()
399 const
400 {
401 return right().evaluate();
402 }
403
404
405 node_negate::node_negate(node operand)
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
420 double node_negate::evaluate_node()
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
435 node_add::node_add(node left, node right)
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
451 double node_add::evaluate_node()
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
466 node_subtract::node_subtract(node left, node right)
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
482 double node_subtract::evaluate_node()
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
497 node_multiply::node_multiply(node left, node right)
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
513 double node_multiply::evaluate_node()
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
528 node_divide::node_divide(node left, node right)
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
544 double node_divide::evaluate_node()
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 }
node_identifier::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:184
node_number::node_number
node_number(double value)
Definition: node_impl.cpp:125
node_binary::left_
node left_
Definition: node_impl.hpp:161
node_identifier::name_
std::string name_
Definition: node_impl.hpp:92
node_binary::evaluate_right
double evaluate_right() const
Definition: node_impl.cpp:398
get_function
node get_function(std::string const &name)
Definition: variables.cpp:65
node_add::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:457
node_impl::save
void save(std::ostream &stream) const
Definition: node_impl.cpp:57
node_function::definition_
node definition_
Definition: node_impl.hpp:111
node_unary::node_unary
node_unary(node operand)
Definition: node_impl.cpp:352
node_function_call::name
std::string name() const
Definition: node_impl.cpp:296
node_subtract::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:488
calc_error
Definition: calc_error.hpp:11
node_void::evaluate_string
virtual std::string evaluate_string() const override
Definition: node_impl.cpp:113
node_impl::evaluate_string
virtual std::string evaluate_string() const
Definition: node_impl.cpp:42
node_identifier::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:178
node_impl::evaluate_node
virtual double evaluate_node() const =0
node_function::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:255
node_function_call::arguments
node_list const & arguments() const
Definition: node_impl.cpp:302
node_divide::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:536
node_impl::node_impl
node_impl()
Definition: node_impl.cpp:12
node_subtract::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:474
node_binary::evaluate_left
double evaluate_left() const
Definition: node_impl.cpp:392
node_number::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:154
node_function_call::node_function_call
node_function_call(std::string name, node_list arguments)
Definition: node_impl.cpp:277
node_void::node_void
node_void()
Definition: node_impl.cpp:93
node_number::value_
double value_
Definition: node_impl.hpp:75
node_binary::node_binary
node_binary(node left, node right)
Definition: node_impl.cpp:372
node_impl
Definition: node_impl.hpp:20
node
Definition: node.hpp:26
calc_error.hpp
node_subtract::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:482
node_multiply::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:513
node_identifier::name
std::string const & name() const
Definition: node_impl.cpp:172
node_void::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:101
node_identifier::evaluate_string
virtual std::string evaluate_string() const override
Definition: node_impl.cpp:190
node_identifier::node_identifier
node_identifier(std::string name)
Definition: node_impl.cpp:161
node_multiply::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:519
node_function::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:246
node_function_call::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:321
node_number::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:148
node_impl::print
void print(std::ostream &stream, int indent) const
Definition: node_impl.cpp:18
node_unary::operand_
node operand_
Definition: node_impl.hpp:143
identifier_list
std::vector< std::string > identifier_list
A sequence of identifiers (e.g., parameter names).
Definition: node.hpp:19
node_impl::read_node
static std::shared_ptr< node_impl > read_node(std::istream &stream)
Definition: node_impl.cpp:64
set_symbol_table
Definition: variables.hpp:19
node_number::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:142
node_binary
Definition: node_impl.hpp:147
node_impl::~node_impl
virtual ~node_impl()
Definition: node_impl.cpp:15
node_identifier::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:196
node_impl.hpp
node_unary
Definition: node_impl.hpp:131
node_binary::right
node right() const
Definition: node_impl.cpp:386
node_function::node_function
node_function(identifier_list parameters, node definition)
Definition: node_impl.cpp:203
node_unary::evaluate_operand
double evaluate_operand() const
Definition: node_impl.cpp:366
node_function::definition
node definition() const
Definition: node_impl.cpp:229
node_multiply::node_multiply
node_multiply(node left, node right)
Definition: node_impl.cpp:497
node_function::evaluate_parameters
virtual identifier_list const & evaluate_parameters() const override
Definition: node_impl.cpp:261
function_error
Definition: calc_error.hpp:31
node_function_call::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:308
node::print
void print(std::ostream &stream, int indent=0) const
Definition: node.cpp:54
node_void::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:119
print_identifier_list
void print_identifier_list(std::ostream &stream, identifier_list const &identifiers)
Definition: node_impl.cpp:235
node_negate::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:413
node_function_call::arguments_
node_list arguments_
Definition: node_impl.hpp:127
node_impl::print_node
virtual void print_node(std::ostream &stream, int indent) const =0
node_function::parameters_
identifier_list parameters_
Definition: node_impl.hpp:110
node_binary::right_
node right_
Definition: node_impl.hpp:162
node_subtract::node_subtract
node_subtract(node left, node right)
Definition: node_impl.cpp:466
node_impl::evaluate
double evaluate() const
Definition: node_impl.cpp:24
node_impl::save_node
virtual void save_node(std::ostream &stream) const =0
node_void::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:107
node_add::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:443
node.hpp
node::evaluate
double evaluate() const
Definition: node.cpp:60
node_impl::evaluate_parameters
virtual identifier_list const & evaluate_parameters() const
Definition: node_impl.cpp:50
node_function::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:267
node_divide::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:544
node::get_parameters
identifier_list const & get_parameters() const
Definition: node.cpp:72
node_impl::get_parameters
identifier_list const & get_parameters() const
Definition: node_impl.cpp:36
node_number::value
double value() const
Definition: node_impl.cpp:136
node_list
std::vector< node > node_list
A sequence of nodes.
Definition: node.hpp:13
node_function_call::name_
std::string name_
Definition: node_impl.hpp:126
node_impl::to_string
std::string to_string() const
Definition: node_impl.cpp:30
node_unary::operand
node operand() const
Definition: node_impl.cpp:360
node::save
void save(std::ostream &stream) const
Definition: node.cpp:78
node_negate::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:426
node_negate::node_negate
node_negate(node operand)
Definition: node_impl.cpp:405
variables.hpp
node_multiply::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:505
node_add::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:451
node_divide::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:550
node_divide::node_divide
node_divide(node left, node right)
Definition: node_impl.cpp:528
node_add::node_add
node_add(node left, node right)
Definition: node_impl.cpp:435
node_binary::left
node left() const
Definition: node_impl.cpp:380
node_function_call::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:343
node_function::parameters
identifier_list const & parameters() const
Definition: node_impl.cpp:223
get_variable
node get_variable(std::string const &name)
Definition: variables.cpp:49
symbol_table
std::map< std::string, node > symbol_table
Definition: variables.hpp:13
node_negate::evaluate_node
virtual double evaluate_node() const override
Definition: node_impl.cpp:420