- Main Page
- Classes
- Files

# 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 }