Calculator Step 6

- 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 number 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 number node_void::evaluate_node()
108 const
109 {
110 return number();
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(number value)
126 : node_impl{}, value_{value}
127 {}
128
129 node_number::node_number(std::istream& stream)
130 : node_impl{}, value_{stream}
131 {}
132
133 number node_number::value()
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
145 number node_number::evaluate_node()
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
160 node_identifier::node_identifier(std::string name)
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
183 number node_identifier::evaluate_node()
184 const
185 {
186 return get_variable(name()).evaluate();
187 }
188
189 std::string node_identifier::evaluate_string()
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
202 node_function::node_function(identifier_list parameters, node definition)
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
222 identifier_list const& node_function::parameters()
223 const
224 {
225 return parameters_;
226 }
227
228 node node_function::definition()
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";
249 print_identifier_list(stream, parameters());
250 stream << '=';
251 definition().print(stream, indent + 2);
252 }
253
254 number node_function::evaluate_node()
255 const
256 {
257 return definition().evaluate();
258 }
259
260 identifier_list const& node_function::evaluate_parameters()
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
276 node_function_call::node_function_call(std::string name, node_list arguments)
277 : node_impl{}, name_{std::move(name)}, arguments_{std::move(arguments)}
278 {}
279
280 node_function_call::node_function_call(std::istream& stream)
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
295 std::string node_function_call::name()
296 const
297 {
298 return name_;
299 }
300
301 node_list const& node_function_call::arguments()
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
320 number node_function_call::evaluate_node()
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
351 node_unary::node_unary(node operand)
352 : node_impl{}, operand_{operand}
353 {}
354
355 node_unary::node_unary(std::istream& stream)
356 : node_impl{}, operand_{stream}
357 {}
358
359 node node_unary::operand()
360 const
361 {
362 return operand_;
363 }
364
365 number node_unary::evaluate_operand()
366 const
367 {
368 return operand().evaluate();
369 }
370
371 node_binary::node_binary(node left, node right)
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
379 node node_binary::left()
380 const
381 {
382 return left_;
383 }
384
385 node node_binary::right()
386 const
387 {
388 return right_;
389 }
390
391 number node_binary::evaluate_left()
392 const
393 {
394 return left().evaluate();
395 }
396
397 number node_binary::evaluate_right()
398 const
399 {
400 return right().evaluate();
401 }
402
403
404 node_negate::node_negate(node operand)
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
419 number node_negate::evaluate_node()
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
434 node_add::node_add(node left, node right)
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
450 number node_add::evaluate_node()
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
465 node_subtract::node_subtract(node left, node right)
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
481 number node_subtract::evaluate_node()
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
496 node_multiply::node_multiply(node left, node right)
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
512 number node_multiply::evaluate_node()
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
527 node_divide::node_divide(node left, node right)
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
543 number node_divide::evaluate_node()
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 }
node_binary::left_
node left_
Definition: node_impl.hpp:164
node_identifier::name_
std::string name_
Definition: node_impl.hpp:95
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:456
node_impl::save
void save(std::ostream &stream) const
Definition: node_impl.cpp:57
node_function::definition_
node definition_
Definition: node_impl.hpp:114
node_unary::node_unary
node_unary(node operand)
Definition: node_impl.cpp:351
node_function_call::name
std::string name() const
Definition: node_impl.cpp:295
node_subtract::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:487
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:177
node_unary::evaluate_operand
number evaluate_operand() const
Definition: node_impl.cpp:365
node_function_call::arguments
node_list const & arguments() const
Definition: node_impl.cpp:301
node_divide::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:535
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:473
number
Definition: number.hpp:16
node_number::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:151
node_function_call::node_function_call
node_function_call(std::string name, node_list arguments)
Definition: node_impl.cpp:276
node_void::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:107
node_void::node_void
node_void()
Definition: node_impl.cpp:93
node_binary::node_binary
node_binary(node left, node right)
Definition: node_impl.cpp:371
node_impl
Definition: node_impl.hpp:20
node
Definition: node.hpp:28
calc_error.hpp
node_impl::evaluate
number evaluate() const
Definition: node_impl.cpp:24
node_identifier::name
std::string const & name() const
Definition: node_impl.cpp:171
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:189
node_identifier::node_identifier
node_identifier(std::string name)
Definition: node_impl.cpp:160
node_multiply::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:518
node_function::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:245
node_binary::evaluate_right
number evaluate_right() const
Definition: node_impl.cpp:397
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:146
node_identifier::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:183
node_function::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:254
node_binary::evaluate_left
number evaluate_left() const
Definition: node_impl.cpp:391
identifier_list
std::vector< std::string > identifier_list
A sequence of identifiers (e.g., parameter names).
Definition: node.hpp:21
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:139
node_binary
Definition: node_impl.hpp:150
node_impl::~node_impl
virtual ~node_impl()
Definition: node_impl.cpp:15
node_number::value
number value() const
Definition: node_impl.cpp:133
node_identifier::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:195
node_impl.hpp
node_unary
Definition: node_impl.hpp:134
node_binary::right
node right() const
Definition: node_impl.cpp:385
node_function::node_function
node_function(identifier_list parameters, node definition)
Definition: node_impl.cpp:202
node_multiply::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:512
node_number::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:145
node_function::definition
node definition() const
Definition: node_impl.cpp:228
node_multiply::node_multiply
node_multiply(node left, node right)
Definition: node_impl.cpp:496
node_function::evaluate_parameters
virtual identifier_list const & evaluate_parameters() const override
Definition: node_impl.cpp:260
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:307
node_number::node_number
node_number(number value)
Definition: node_impl.cpp:125
number::save
void save(std::ostream &stream) const
Definition: number.cpp:39
node::print
void print(std::ostream &stream, int indent=0) const
Definition: node.cpp:67
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:234
node_negate::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:419
node_negate::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:412
node_function_call::arguments_
node_list arguments_
Definition: node_impl.hpp:130
node_subtract::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:481
node_impl::print_node
virtual void print_node(std::ostream &stream, int indent) const =0
node_impl::evaluate_node
virtual number evaluate_node() const =0
node::evaluate
number evaluate() const
Definition: node.cpp:73
node_function::parameters_
identifier_list parameters_
Definition: node_impl.hpp:113
node_binary::right_
node right_
Definition: node_impl.hpp:165
node_subtract::node_subtract
node_subtract(node left, node right)
Definition: node_impl.cpp:465
node_impl::save_node
virtual void save_node(std::ostream &stream) const =0
node_add::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:442
node.hpp
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:266
node_number::value_
number value_
Definition: node_impl.hpp:78
node::get_parameters
identifier_list const & get_parameters() const
Definition: node.cpp:85
node_impl::get_parameters
identifier_list const & get_parameters() const
Definition: node_impl.cpp:36
node_list
std::vector< node > node_list
A sequence of nodes.
Definition: node.hpp:15
node_function_call::name_
std::string name_
Definition: node_impl.hpp:129
node_function_call::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:320
node_impl::to_string
std::string to_string() const
Definition: node_impl.cpp:30
node_unary::operand
node operand() const
Definition: node_impl.cpp:359
node::save
void save(std::ostream &stream) const
Definition: node.cpp:91
node_divide::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:543
node_negate::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:425
node_negate::node_negate
node_negate(node operand)
Definition: node_impl.cpp:404
variables.hpp
node_multiply::print_node
virtual void print_node(std::ostream &stream, int indent) const override
Definition: node_impl.cpp:504
node_divide::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:549
node_divide::node_divide
node_divide(node left, node right)
Definition: node_impl.cpp:527
node_add::node_add
node_add(node left, node right)
Definition: node_impl.cpp:434
node_binary::left
node left() const
Definition: node_impl.cpp:379
node_function_call::save_node
virtual void save_node(std::ostream &stream) const override
Definition: node_impl.cpp:342
node_function::parameters
identifier_list const & parameters() const
Definition: node_impl.cpp:222
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_add::evaluate_node
virtual number evaluate_node() const override
Definition: node_impl.cpp:450