Calculator Step 5

- Main Page
- Classes
- Files

- File List
- File Members

variables.cpp
Go to the documentation of this file.
1 #include <fstream>
2 #include <istream>
3 #include <limits>
4 #include <map>
5 #include <ostream>
6
7 #include "calc_error.hpp"
8 #include "node.hpp"
9 #include "variables.hpp"
10
11 namespace {
12 symbol_table variables;
13 std::vector<symbol_table const*> symbol_tables;
14
15 class initializer {
16 public:
17 initializer() {
18 variables["pi"] = node(3.141592653589792);
19 variables["e"] = node(2.718281828459);
20 symbol_tables.push_back(&variables);
21 }
22 };
23 initializer init;
24 }
25
26 set_symbol_table::set_symbol_table(symbol_table const& locals)
27 {
28 symbol_tables.push_back(&locals);
29 }
30
31 set_symbol_table::~set_symbol_table()
32 {
33 symbol_tables.pop_back();
34 }
35
36 bool find_symbol(std::string const& name, node& value)
37 {
38 for (auto iter(symbol_tables.rbegin()), end(symbol_tables.rend()); iter != end; ++iter) {
39 symbol_table const& table{ **iter };
40 symbol_table::const_iterator entry{ table.find(name) };
41 if (entry != table.end()) {
42 value = entry->second;
43 return true;
44 }
45 }
46 return false;
47 }
48
49 node get_variable(std::string const& name)
50 {
51 node result{};
52 if (not find_symbol(name, result))
53 return node{};
54 else if (result.get_parameters().empty())
55 return result;
56 else
57 throw function_error{name, result.get_parameters().size(), 0};
58 }
59
60 void set_variable(std::string const& name, node value)
61 {
62 variables[name] = value;
63 }
64
65 node get_function(std::string const& name)
66 {
67 node result{};
68 if (not find_symbol(name, result))
69 throw no_such_function{name};
70 else
71 return result;
72 }
73
74 void set_function(std::string const& name, node value)
75 {
76 set_variable(name, value);
77 }
78
79 void save_library(std::string const& filename)
80 {
81 std::ofstream stream{filename.c_str()};
82 if (not stream)
83 throw file_error{filename};
84 // Be sure to save numbers with maximum precision.
85 stream.precision(std::numeric_limits<double>::digits10);
86 stream << ":library:\n";
87 for (auto const& symbol : variables)
88 {
89 stream << symbol.first << ' ';
90 symbol.second.save(stream);
91 if (stream.fail())
92 throw file_error{filename};
93 }
94 stream << "*\n";
95 stream.close();
96 if (stream.fail())
97 throw file_error{filename};
98 }
99
100 void load_library(std::string const& filename)
101 {
102 std::ifstream stream{filename.c_str()};
103 if (not stream)
104 throw file_error{filename};
105 std::string token{};
106 if (not std::getline(stream, token))
107 throw calc_error{filename + ": is empty"};
108 if (token != ":library:")
109 throw calc_error{filename + ": is not a calculator library file"};
110 while (stream >> token) {
111 if (token == "*")
112 return;
113 else
114 set_variable(token, node{stream});
115 }
116 }
load_library
void load_library(std::string const &filename)
Definition: variables.cpp:100
get_function
node get_function(std::string const &name)
Definition: variables.cpp:65
find_symbol
bool find_symbol(std::string const &name, node &value)
Definition: variables.cpp:36
calc_error
Definition: calc_error.hpp:11
save_library
void save_library(std::string const &filename)
Definition: variables.cpp:79
node
Definition: node.hpp:26
calc_error.hpp
set_variable
void set_variable(std::string const &name, node value)
Definition: variables.cpp:60
set_function
void set_function(std::string const &name, node value)
Definition: variables.cpp:74
function_error
Definition: calc_error.hpp:31
file_error
Definition: calc_error.hpp:50
no_such_function
Definition: calc_error.hpp:42
set_symbol_table::~set_symbol_table
~set_symbol_table()
Definition: variables.cpp:31
node.hpp
variables.hpp
set_symbol_table::set_symbol_table
set_symbol_table(symbol_table const &symtab)
Definition: variables.cpp:26
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