variables.cpp

Go to the documentation of this file.
00001 #include <fstream>
00002 #include <istream>
00003 #include <limits>
00004 #include <map>
00005 #include <ostream>
00006 
00007 #include "calc_error.hpp"
00008 #include "node.hpp"
00009 #include "variables.hpp"
00010 
00011 namespace {
00012   symbol_table variables;
00013   std::vector<symbol_table const*> symbol_tables;
00014 
00015   class initializer {
00016   public:
00017     initializer() {
00018       variables["pi"] = node(3.141592653589792);
00019       variables["e"]  = node(2.718281828459);
00020       symbol_tables.push_back(&variables);
00021     }
00022   };
00023   initializer init;
00024 }
00025 
00026 set_symbol_table::set_symbol_table(symbol_table const& locals)
00027 {
00028   symbol_tables.push_back(&locals);
00029 }
00030 
00031 set_symbol_table::~set_symbol_table()
00032 {
00033   symbol_tables.pop_back();
00034 }
00035 
00036 bool find_symbol(std::string const& name, node& value)
00037 {
00038   for (std::vector<symbol_table const*>::reverse_iterator iter(symbol_tables.rbegin()); iter != symbol_tables.rend(); ++iter) {
00039     symbol_table const& table( **iter );
00040     symbol_table::const_iterator entry = table.find(name);
00041     if (entry != table.end()) {
00042       value = entry->second;
00043       return true;
00044     }
00045   }
00046   return false;
00047 }
00048 
00049 node get_variable(std::string const& name)
00050 {
00051   node result;
00052   if (not find_symbol(name, result))
00053     return node();
00054   else if (result.get_parameters().empty())
00055     return result;
00056   else
00057     throw function_error(name, result.get_parameters().size(), 0);
00058 }
00059 
00060 void set_variable(std::string const& name, node value)
00061 {
00062   variables[name] = value;
00063 }
00064 
00065 node get_function(std::string const& name)
00066 {
00067   node result;
00068   if (not find_symbol(name, result))
00069     throw no_such_function(name);
00070   else
00071     return result;
00072 }
00073 
00074 void set_function(std::string const& name, node value)
00075 {
00076   set_variable(name, value);
00077 }
00078 
00079 void save_library(std::string const& filename)
00080 {
00081   std::ofstream stream(filename.c_str());
00082   if (not stream)
00083     throw file_error(filename);
00084   // Be sure to save numbers with maximum precision.
00085   stream.precision(std::numeric_limits<double>::digits10);
00086   stream << ":library:\n";
00087   for (symbol_table::iterator symbol(variables.begin()); symbol != variables.end(); ++symbol) {
00088     stream << symbol->first << ' ';
00089     symbol->second.save(stream);
00090     if (stream.fail())
00091       throw file_error(filename);
00092   }
00093   stream << "*\n";
00094   stream.close();
00095   if (stream.fail())
00096     throw file_error(filename);
00097 }
00098 
00099 void load_library(std::string const& filename)
00100 {
00101   std::ifstream stream(filename.c_str());
00102   if (not stream)
00103     throw file_error(filename);
00104   std::string token;
00105   if (not std::getline(stream, token))
00106     throw calc_error(filename + ": is empty");
00107   if (token != ":library:")
00108     throw calc_error(filename + ": is not a calculator library file");
00109   while (stream >> token) {
00110     if (token == "*")
00111       return;
00112     else
00113       set_variable(token, node(stream));
00114   }
00115 }

Generated on Sun Nov 30 10:06:52 2008 for Calculator by  doxygen 1.5.3