#include #include #include #include #include #include #include "variable_list.hpp" class parser { public: typedef std::tr1::function error_callback_type; typedef std::tr1::function warning_callback_type; void set_callbacks(const warning_callback_type& warning_callback, const error_callback_type& error_callback) { warning_callback_ = warning_callback; error_callback_ = error_callback; } private: typedef boost::mpl::vector types; template struct callback_type { typedef std::tr1::function type; }; typedef variable_list > callback_variable_list_type; callback_variable_list_type callback_variable_list_; public: template void set_callback(const typename callback_type::type& callback) { callback_variable_list_.get() = callback; } template struct set_callback_functor { set_callback_functor(parser& p, CallbackFunctor callback_functor) : p_(p), callback_functor_(callback_functor) {} template void operator()(const T&) { p_.set_callback(callback_functor_(T())); } parser& p_; CallbackFunctor callback_functor_; }; template void set_callbacks(CallbackFunctor callback_functor) { boost::mpl::for_each(set_callback_functor(*this, callback_functor)); } bool parse(std::istream& istream) { std::string line; std::size_t line_number = 0; while (std::getline(istream, line)) { ++line_number; std::istringstream stringstream(line); stringstream >> std::ws; if (stringstream.eof()) { } else { std::string type; stringstream >> type; if (type == "bool") { bool value; stringstream >> value; if (callback_variable_list_.get()) callback_variable_list_.get()(value); } else if (type == "char") { char value; stringstream >> value; if (callback_variable_list_.get()) callback_variable_list_.get()(value); } else if (type == "short") { short value; stringstream >> value; if (callback_variable_list_.get()) callback_variable_list_.get()(value); } else if (type == "int") { int value; stringstream >> value; if (callback_variable_list_.get()) callback_variable_list_.get()(value); } else if (type == "long") { long value; stringstream >> value; if (callback_variable_list_.get()) callback_variable_list_.get()(value); } else if (type == "float") { float value; stringstream >> value; if (callback_variable_list_.get()) callback_variable_list_.get()(value); } else if (type == "double") { double value; stringstream >> value; if (callback_variable_list_.get()) callback_variable_list_.get()(value); } else { if (error_callback_) { error_callback_(line_number, "parser error"); return false; } } } } return !istream.fail() && istream.eof() && !istream.bad();; } private: error_callback_type error_callback_; warning_callback_type warning_callback_; }; void error_callback(const std::string& filename, std::size_t line, const std::string& message) { std::cerr << filename << ":" << line << ": " << "error: " << message << std::endl; } void warning_callback(const std::string& filename, std::size_t line, const std::string& message) { std::cerr << filename << ":" << line << ": " << "warning: " << message << std::endl; } template void callback(T value) { std::cout << typeid(T).name() << " " << value << "\n"; } struct callback_functor { template std::tr1::function operator()(const T&) const { return std::tr1::function(&callback); } }; int main(int argc, char* argv[]) { std::string filename; parser p; p.set_callbacks( std::tr1::bind(error_callback, std::tr1::ref(filename), std::tr1::placeholders::_1, std::tr1::placeholders::_2), std::tr1::bind(warning_callback, std::tr1::ref(filename), std::tr1::placeholders::_1, std::tr1::placeholders::_2) ); p.set_callbacks(callback_functor()); filename = "stringstream"; std::stringstream stringstream("bool 1\nchar 2\nshort 3\nint 4\nlong 5\nfloat 6.0\ndouble 7.0"); p.parse(stringstream); }