diff --git a/doc/manual/libmultiscale_doc_parser.cc b/doc/manual/libmultiscale_doc_parser.cc index 54905a5..c26aea0 100644 --- a/doc/manual/libmultiscale_doc_parser.cc +++ b/doc/manual/libmultiscale_doc_parser.cc @@ -1,358 +1,366 @@ /** * @file libmultiscale_doc_parser.cc * * @author Guillaume Anciaux * * @date Fri Oct 10 16:40:09 2014 * * @brief Manual parser * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * LibMultiScale is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * LibMultiScale is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with LibMultiScale. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "libmultiscale_doc_parser.hh" /* -------------------------------------------------------------------------- */ +#include #include #include #include #include #include + +#if (BOOST_VERSION/100)%1000 <= 55 +#include +#include +#else #include #include +#endif + #include #include #include using namespace boost::filesystem; /* -------------------------------------------------------------------------- */ using namespace boost::spirit; /* -------------------------------------------------------------------------- */ typedef unsigned int UInt; /* -------------------------------------------------------------------------- */ #define _call(x) boost::phoenix::bind(&LibMultiScaleDocParser::x,this) #define _call1(x,p1) boost::phoenix::bind(&LibMultiScaleDocParser::x,this,p1) #define _call2(x,p1,p2) boost::phoenix::bind(&LibMultiScaleDocParser::x,this,p1,p2) #define _call3(x,p1,p2,p3) boost::phoenix::bind(&LibMultiScaleDocParser::x,this,p1,p2,p3) #define _call4(x,p1,p2,p3,p4) boost::phoenix::bind(&LibMultiScaleDocParser::x,this,p1,p2,p3,p4) /* -------------------------------------------------------------------------- */ std::string debug(const std::string & v){ std::cerr << "AAAAAAAAAA " << v << " AAAAAAAAAAAAA" << std::endl; return v; } #define _dbg(x,p1) boost::phoenix::bind(&debug,p1) /* -------------------------------------------------------------------------- */ template LibMultiScaleDocParser::LibMultiScaleDocParser() : LibMultiScaleDocParser::base_type(start,"start") { std::string stag_desc = "/* LMDESC"; std::string etag_desc = "*/"; std::string stag_keyword = "/* LMKEYWORD"; std::string etag_keyword = "*/"; std::string stag_heritance = "/* LMHERITANCE"; std::string etag_heritance = "*/"; std::string stag_example = "/* LMEXAMPLE"; std::string etag_example = "*/"; using qi::char_; using qi::print; using qi::space; using qi::alnum; using qi::alpha; using qi::string; using qi::lexeme; using qi::on_error; using qi::fail; using boost::phoenix::ref; using boost::phoenix::val; using boost::phoenix::construct; using boost::phoenix::at_c; using boost::phoenix::push_back; start = text(stag_desc) > description[_val = _1] >> *(*(char_ - string(stag_keyword) - string(stag_heritance) - string(stag_example)) >> (heritance[at_c<7>(_val) = _1] | keyword[push_back(at_c<3>(_val),_1)] | example[at_c<8>(_val) = _1] ) ); lookup_todo = *(char_ - string("TODO")) > eoi; lookup_type = *(string("return") | (char_ - declaration(_r1))) > declaration(_r1)[_val = _1]; lookup_syntax = *(char_ - string("LMSYNTAX")) > eoi; // quantity_type = string("Quantity<") > name > string(">"); vec_quantity_type = string("Quantity<") > name > - string(",") > *(char_ - '>') > string(">"); c_type = +(char_ - "return" - eol - space - "{" - "}" - "<<" - ">>" ); declaration = ( vec_quantity_type // | quantity_type | c_type)[_val = _1] >> +space >> string(_r1) >> brackets[_val += _1] >> ';'; brackets = -(string("[") > *(char_ -string("]")) > string("]")); description = lit(stag_desc) > (*space) > name[at_c<0>(_val) = _1] > *(space-eol) > eol[at_c<1>(_val) = val("class")] > innertext(etag_desc)[at_c<2>(_val) = _1] > lit(etag_desc); defaults = *(char_-')'); keyword = lit(stag_keyword) > name[at_c<0>(_val) = _1] > eol > innertext(etag_desc)[at_c<2>(_val) = _1] > lit(etag_keyword) > *eol > ((( string("this->parseTag")[at_c<1>(_val) = "Tag"] |string("this->parseKeyword")[at_c<1>(_val) = "Keyword"] ) > "(\"" > string(at_c<0>(_val)) > "\"," > *string("this->") > name[at_c<4>(_val) = _1] > *(char_-")"-",") > -(string(",") > defaults[at_c<9>(_val) = _1])) |(string("this->parseVectorKeyword")[at_c<1>(_val) = "Keyword ["] > "(\"" > string(at_c<0>(_val)) > "\"," > expr[at_c<1>(_val) += _1 + val(std::string("]"))] > "," > *string("this->") > name[at_c<4>(_val) = _1] > -( string(",") > string("VEC_DEFAULTS(") > defaults[at_c<9>(_val) = _1] > string(")"))) ) > string(");"); expr = *(char_ - string(",") - space); heritance = lit(stag_heritance) > (*space) > *(name[push_back(_val,_1)] > *(space-eol)) > lit(etag_heritance) > eol; example = lit(stag_example) > (*space) > *(char_ - string(etag_example)) > lit(etag_example) > eol; // parse everything but a starting tag text = *(char_ - string(_r1)); // // parse a single name name = +(alnum|string("_")); // // parse everything but the end tag innertext = *(char_ - string(_r1)); description.name("description"); lookup_type.name("lookup_type"); lookup_todo.name("lookup_todo"); heritance.name("heritance"); start.name("start"); c_type.name("c_type"); declaration.name("declaration"); name.name("name"); text.name("text"); innertext.name("innertext"); keyword.name("keyword"); expr.name("expr"); example.name("example"); on_error(start,_call4(errorHandlerMain,_1,_2,_3,_4)); on_error(lookup_type,_call4(errorHandlerMain,_1,_2,_3,_4)); on_error(lookup_todo,_call4(errorHandlerTodo,_1,_2,_3,_4)); on_error(lookup_syntax,_call4(errorHandlerSyntax,_1,_2,_3,_4)); } /* -------------------------------------------------------------------------- */ template bool LibMultiScaleDocParser::parse(LMDocData & result, std::set & internal_key_list){ fname = result.filename.native(); std::ifstream file(result.filename.c_str()); if (!file.good()) std::cerr << "could not open file: " << result.filename << std::endl; std::string str((std::istreambuf_iterator(file)), std::istreambuf_iterator()); iter = str.begin(); end = str.end(); bool parsed = qi::phrase_parse(iter, end, start, boost::spirit::ascii::blank,result); result.filename = fname; if (result.example == "" && internal_key_list.count(result.name) == 0){ std::cerr << fname << ":0:Warning: no LMEXAMPLE found in that class" << std::endl; } else if (result.example != "" && internal_key_list.count(result.name) != 0){ std::cerr << fname << ":0:Warning: an example was provided for an internal class" << std::endl; } if (!parsed) return parsed; iter = str.begin(); std::string todo; qi::parse(iter, end, lookup_todo,todo); if (!parsed) return parsed; iter = str.begin(); std::string syntax; qi::parse(iter, end, lookup_syntax,syntax); for (UInt i = 0; i < result.children.size(); ++i) { LMDocData & child = result.children[i]; // if (child.type == "Tag" || // child.type == "Keyword" || // child.type == "Keyword []"){ path cc_file = result.filename; path hh_file = cc_file.replace_extension(path(".hh")); std::string h_fname = hh_file.native(); std::ifstream hfile(h_fname.c_str()); if (hfile.is_open() == false){ std::cerr << "fname:0:Error: cannot find header file " << h_fname << std::endl; return false; } std::string hstr((std::istreambuf_iterator(hfile)), std::istreambuf_iterator()); iter = hstr.begin(); end = hstr.end(); std::string c_type; // std::cerr << "look for parameter " << child.name << " " << child.var_name << " " << child.type << std::endl; parsed &= qi::parse(iter, end, lookup_type(child.var_name),c_type); if (!parsed){ std::cerr << h_fname << ":" << 0 << ":Error could not parse variable " << child.name << " " << child.var_name << " " << child.type << std::endl; return parsed; } // std::cerr << "found parameter " << child.name << " " << child.var_name << " " << c_type << std::endl; child.c_type = c_type; // } iter = hstr.begin(); std::string todo; qi::parse(iter, end, lookup_todo,todo); if (!parsed) return parsed; iter = hstr.begin(); std::string syntax; qi::parse(iter, end, lookup_syntax,syntax); } return parsed; } /* -------------------------------------------------------------------------- */ template int LibMultiScaleDocParser::getLineNumber(const std::string & text, std::string & now_parsing){ int last_index = 0; UInt count_lines = 0; size_t index = text.find_first_of("\n", 0); while (index != text.npos){ count_lines++; last_index = index; index = text.find_first_of("\n", last_index + 1); // std::cerr << last_index << " " << index << std::endl; } // std::cerr << last_index << " " << index << std::endl; now_parsing = text.substr(last_index+1,index); return count_lines; } /* -------------------------------------------------------------------------- */ template void LibMultiScaleDocParser::errorHandlerMain(const std::string::const_iterator & a, const std::string::const_iterator& b, const std::string::const_iterator & c, const info & what){ std::string already_parsed(a,c); std::string now_parsing; UInt count_lines = getLineNumber(already_parsed,now_parsing); std::string not_parsed = std::string(c,b); int index = not_parsed.find_first_of("\n",0); std::string mess = now_parsing + " ^^^^ " + not_parsed.substr(0,index); std::cerr << fname << ":" << count_lines+1 << ":Error Expecting " << what << " here: \"" << mess << "\"" << std::endl; } /* -------------------------------------------------------------------------- */ template void LibMultiScaleDocParser::errorHandlerTodo(const std::string::const_iterator & a, const std::string::const_iterator& b, const std::string::const_iterator & c, const info & what){ std::string already_parsed(a,c); // std::cerr << "already parsed " << already_parsed << std::endl; std::string now_parsing; UInt count_lines = getLineNumber(already_parsed,now_parsing); std::cerr << fname << ":" << count_lines+1 << ":Warning TODO remaining: " << what << ": " << now_parsing < void LibMultiScaleDocParser::errorHandlerSyntax(const std::string::const_iterator & a, const std::string::const_iterator& b, const std::string::const_iterator & c, const info & what){ std::string already_parsed(a,c); // std::cerr << "already parsed " << already_parsed << std::endl; std::string now_parsing; UInt count_lines = getLineNumber(already_parsed,now_parsing); std::cerr << fname << ":" << count_lines+1 << ":Warning old Syntax remaining: " << what << ": " << now_parsing <; diff --git a/packages/boost.cmake b/packages/boost.cmake new file mode 100644 index 0000000..af01b66 --- /dev/null +++ b/packages/boost.cmake @@ -0,0 +1,47 @@ +#=============================================================================== +# @file boost.cmake +# +# @author Nicolas Richart +# +# @date creation: Wed Jan 14 2015 +# +# @brief package handling the dependencies to boost +# +# @section LICENSE +# +# Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see . +# +#=============================================================================== + +package_declare(Boost EXTERNAL + NOT_OPTIONAL + DESCRIPTION "Package handling boost components" + EXTRA_PACKAGE_OPTIONS PREFIX Boost + ) + +mark_as_advanced(Boost_DIR) + +package_on_enabled_script(Boost + "if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER \"4.8\") + set(_boost_version \${Boost_MAJOR_VERSION}.\${Boost_MINOR_VERSION}) + if(AKANTU_CORE_CXX11 AND _boost_version VERSION_LESS 1.58) + add_flags(cxx -DBOOST_RESULT_OF_USE_TR1) + else() + remove_flags(cxx -DBOOST_RESULT_OF_USE_TR1) + endif() +endif() +") diff --git a/packages/mandatory_packages.cmake b/packages/mandatory_packages.cmake index c2c0165..e7c1855 100644 --- a/packages/mandatory_packages.cmake +++ b/packages/mandatory_packages.cmake @@ -1,70 +1,70 @@ #=============================================================================== # @file mandatory_packages.cmake # # @author Guillaume Anciaux # @author Nicolas Richart # # @date Wed Mar 06 12:17:42 2013 # # @brief All mandatory packages # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # LibMultiScale is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # LibMultiScale is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with LibMultiScale. If not, see . # #=============================================================================== package_declare(mandatory_packages NOT_OPTIONAL DESCRIPTION "meta package for mandatory external packages" - DEPENDS PythonLibs lapack mpi expat fftw gsl zlib #boost fftw expat zlib + DEPENDS PythonLibs lapack mpi expat fftw gsl zlib boost ) #add_external_package(MPI) # #add_external_package(Boost PREFIX Boost) #list(APPEND LIBMULTISCALE_EXTERNAL_LIB_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/src) #list(APPEND LIBMULTISCALE_BOOST_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/src/boost) # ##Not using the macro because the python module is shity #find_package(PythonLibs REQUIRED 2.7) #if(PYTHONLIBS_FOUND) # list(APPEND LIBMULTISCALE_DEFINITIONS LIBMULTISCALE_USE_PYTHON) # list(APPEND LIBMULTISCALE_EXTERNAL_LIB_INCLUDE_DIR ${PYTHON_INCLUDE_DIR}) # list(APPEND LIBMULTISCALE_EXTERNAL_LIBRARIES ${PYTHON_LIBRARIES}) # # set(LIBMULTISCALE_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR}) # set(LIBMULTISCALE_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) # set(LIBMULTISCALE_PYTHON ON) # # list(APPEND LIBMULTISCALE_OPTION_LIST PYTHON) #endif() # #add_external_package(FFTW) #add_external_package(GSL) #add_external_package(LAPACK) #add_external_package(EXPAT) #add_optional_external_package(QVIEW "Activate the QView monitoring feature" OFF) #if (LIBMULTISCALE_USE_QVIEW) # add_definitions(-DUSING_QVIEW) #endif(LIBMULTISCALE_USE_QVIEW) #mark_as_advanced(LIBMULTISCALE_USE_QVIEW) # #add_optional_external_package(ZLIB "Activate the ZLIB compression feature" OFF) #if (LIBMULTISCALE_USE_ZLIB) # add_definitions(-DLIBMULTISCALE_USE_ZLIB) #endif(LIBMULTISCALE_USE_ZLIB) # diff --git a/src/parser/algebraic_parser.cc b/src/parser/algebraic_parser.cc index 020beba..cbe523e 100644 --- a/src/parser/algebraic_parser.cc +++ b/src/parser/algebraic_parser.cc @@ -1,318 +1,326 @@ /** * @file algebraic_parser.cc * * @author Guillaume Anciaux * * @date Wed Mar 13 16:53:59 2013 * * @brief The algebraic expression parser for LM config files * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * LibMultiScale is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * LibMultiScale is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with LibMultiScale. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "lm_common.hh" #include #include "algebraic_parser.hh" #include "lm_parser.hh" /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ +#include #include #include #include #include #include +#if (BOOST_VERSION/100)%1000 <= 55 +#include +#include +#else #include #include +#endif + + /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ __BEGIN_LIBMULTISCALE__ template struct AlgebraicParser : boost::spirit::qi::grammar { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: AlgebraicParser(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: private: inline double set_var_value(double const & val, std::string const & var_name) const; inline double get_env_var(std::string const & var_name) const; inline double get_var_value(std::string const& var_name) const; inline double get_func_result(double const& entry, std::string const & func_name) const; inline double debug_double(double const& test) const; inline std::string debug_string(std::string const& test) const; inline std::string get_string(std::vector const & vec) const; inline std::string concat_string(std::vector const & vec, std::string const & str2) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: //! grammar rules boost::spirit::qi::rule > set_var; boost::spirit::qi::rule item; boost::spirit::qi::rule > obj_name; boost::spirit::qi::rule > func; boost::spirit::qi::rule num; boost::spirit::qi::rule env_var; boost::spirit::qi::rule term; boost::spirit::qi::rule factor; boost::spirit::qi::rule start; boost::spirit::qi::rule white_space; public: //! map of functions std::map function_maps; //! map of variables and values mutable std::map variables; }; /* -------------------------------------------------------------------------- */ template inline double AlgebraicParser::debug_double(double const& test) const{ std::cerr << "parsing " << test << std::endl; return test; } /* -------------------------------------------------------------------------- */ template inline std::string AlgebraicParser::debug_string(std::string const& test) const{ std::cerr << "parsing " << test << std::endl; return test; } /* -------------------------------------------------------------------------- */ template inline std::string AlgebraicParser::get_string(std::vector const & vec) const{ std::string str = std::string(vec.begin(),vec.end()); return str; } /* -------------------------------------------------------------------------- */ template inline std::string AlgebraicParser::concat_string(std::vector const & vec, std::string const & str2) const{ std::string str = std::string(vec.begin(),vec.end()); return str2+str; } /* -------------------------------------------------------------------------- */ template inline double AlgebraicParser::get_var_value(std::string const& vname) const{ if (vname[0] == '$'){ std::string env_varname = vname.substr(1); char * var = getenv(env_varname.c_str()); if (var == NULL) LM_THROW("unknown environment variable " << env_varname); return (atof(var)); } else { std::map::const_iterator it = variables.find(vname); if (it == variables.end()) LM_THROW("unknown variable " << vname); return (*it).second; } } /* -------------------------------------------------------------------------- */ template inline double AlgebraicParser::set_var_value(double const& val, std::string const & vname) const{ DUMPFILE(Parser::fout,"LET " << vname << " = " << val); variables[vname] = val; return val; } /* -------------------------------------------------------------------------- */ template inline double AlgebraicParser::get_env_var(std::string const & vname) const{ char * var = getenv(vname.c_str()); if (var == NULL) LM_THROW("unknown env variable " << vname); std::string vvname(var); if (variables.count(var)) return variables[vvname]; return atof(var); } /* -------------------------------------------------------------------------- */ template inline double AlgebraicParser::get_func_result(double const& entry, std::string const & func_name) const{ std::map::const_iterator it = function_maps.find(func_name); if (it == function_maps.end()) LM_THROW("unknown function " << func_name); return (*(*it).second)(entry); } /* -------------------------------------------------------------------------- */ #define _call(x) boost::phoenix::bind(&AlgebraicParser::x,this,_1) #define _call2(x) boost::phoenix::bind(&AlgebraicParser::x,this,_1,_a) /* -------------------------------------------------------------------------- */ template AlgebraicParser:: AlgebraicParser() : AlgebraicParser::base_type(start) { using boost::spirit::_val; using boost::spirit::lit; using boost::spirit::standard::space; using boost::spirit::standard::alnum; using boost::spirit::standard::alpha; using boost::spirit::double_; using boost::spirit::int_; using boost::spirit::eoi; using boost::spirit::_1; using boost::spirit::_a; using boost::phoenix::ref; using boost::phoenix::val; set_var = *space >> obj_name[_a = _1] >> *space >> "=" >> term[_val = _call2(set_var_value)]; obj_name = (+alpha)[_a = _call(get_string)] >> (*alnum)[_val = _call2(concat_string)]; func = obj_name[_a = _1] >> "(" >> term[_val = _call2(get_func_result)] >> ")"; env_var = "$" >> obj_name[_val = _call(get_env_var)]; num = *space >> (double_[_val = _1] | "(" >> term[_val = _1] >> ")" | func[_val = _1] | obj_name[_val = _call(get_var_value)] | env_var[_val = _1] ) >> *space; item = *space >> "-" >> num[_val = val(-1.)*_1] | num[_val = _1]; factor = item[_val = _1] >> *(("*" >> item[_val *= _1]) | ("/" >> item[_val /= _1])); term = factor[_val = _1] >> *(("+" >> factor[_val += _1]) | ("-" >> factor[_val -= _1])) ; start = (set_var[_val = _1] | term[_val = _1]) >> *space >> eoi; //setting the default variables and functions variables["pi"] = M_PI; variables["avogadro"] = avogadro; variables["boltzmann"] = boltzmann; function_maps["cos"] = std::cos; function_maps["acos"] = std::acos; function_maps["sin"] = std::sin; function_maps["sqrt"] = std::sqrt; function_maps["abs"] = std::abs; function_maps["atan"] = std::atan; } /* -------------------------------------------------------------------------- */ AlgebraicExpressionParser::AlgebraicExpressionParser(){ my_parser = new AlgebraicParser(); } /* -------------------------------------------------------------------------- */ AlgebraicExpressionParser::~AlgebraicExpressionParser(){ delete my_parser; } /* -------------------------------------------------------------------------- */ bool AlgebraicExpressionParser::parse(const std::string & str, double & result){ std::string::const_iterator iter = str.begin(); std::string::const_iterator end = str.end(); bool parsed = boost::spirit::qi::parse(iter, end, *my_parser, result); if (!parsed) { std::string rest(iter, end); LM_THROW("could not parse -- stopped at " << rest); } return parsed; }; /* -------------------------------------------------------------------------- */ Real & AlgebraicExpressionParser::operator [] (const std::string & var_name){ LM_ASSERT(doesExist(var_name),"Unknown variable"); return my_parser->variables[var_name]; } /* -------------------------------------------------------------------------- */ void AlgebraicExpressionParser::eraseVariable(const std::string & var_name){ my_parser->variables.erase(var_name); } /* -------------------------------------------------------------------------- */ bool AlgebraicExpressionParser::doesExist(const std::string & var_name){ if (my_parser->variables.count(var_name)) return true; return false; } /* -------------------------------------------------------------------------- */ std::map & AlgebraicExpressionParser::getVariables(){ return my_parser->variables; } __END_LIBMULTISCALE__