Calculator  Step 5
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 
27 {
28  symbol_tables.push_back(&locals);
29 }
30 
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 }
void load_library(std::string const &filename)
Definition: variables.cpp:100
node get_function(std::string const &name)
Definition: variables.cpp:65
bool find_symbol(std::string const &name, node &value)
Definition: variables.cpp:36
void save_library(std::string const &filename)
Definition: variables.cpp:79
Definition: node.hpp:26
void set_variable(std::string const &name, node value)
Definition: variables.cpp:60
void set_function(std::string const &name, node value)
Definition: variables.cpp:74
set_symbol_table(symbol_table const &symtab)
Definition: variables.cpp:26
node get_variable(std::string const &name)
Definition: variables.cpp:49
std::map< std::string, node > symbol_table
Definition: variables.hpp:13