Page MenuHomec4science

lm_parser.cc
No OneTemporary

File Metadata

Created
Sun, Sep 29, 03:58

lm_parser.cc

/**
* @file lm_parser.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Wed Jul 02 16:25:38 2014
*
* @brief This is the central parser for LM
*
* @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 <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "lm_parser.hh"
#include "domain_multiscale.hh"
#include "factory_multiscale.hh"
#include "filter_interface.hh"
#include "lm_common.hh"
#include "lm_parsable.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
std::string Parser::getCurrentConfigFile() { return opened_files.back(); }
/* -------------------------------------------------------------------------- */
UInt Parser::getCurrentLine() { return current_line.back(); }
/* -------------------------------------------------------------------------- */
// void Parser::parseGeometry(GeomID & g,stringstream & line){
// parseString(g,line);
// __attribute__((unused)) Geometry * geom =
// GeometryManager::getManager().getGeometry(g);
//}
/* -------------------------------------------------------------------------- */
void Parser::freeMemory() {
// math_parser.free_memory();
// DUMPFILE(fout,"memory cleaned");
fout.close();
}
/* -------------------------------------------------------------------------- */
void Parser::getLine(std::ifstream &file, std::string &line,
UInt &current_line) {
line = "";
std::string tmp_line;
getline(file, tmp_line);
size_t found = tmp_line.find("\\");
++current_line;
while (found != std::string::npos) {
line += tmp_line.substr(0, found - 1);
getline(file, tmp_line);
found = tmp_line.find("\\");
++current_line;
}
line += tmp_line;
}
/* -------------------------------------------------------------------------- */
void Parser::rewindToLine(UInt line) {
DUMPFILE(Parser::fout, "rewind to line" << line);
std::ifstream &f = *opened_ifstreams.back();
f.seekg(0, std::ios_base::beg);
std::string buffer;
current_line.back() = 0;
for (UInt i = 0; i < line - 1; ++i) {
Parser::getLine(f, buffer, current_line.back());
if (current_line.back() == line - 1)
break;
}
}
/* -------------------------------------------------------------------------- */
void Parser::parseConfigFile(const std::string &file,
const std::string &section_name,
const std::string &section_id, Parsable &obj) {
std::ifstream f;
f.open(file.c_str());
if (!f.is_open()) {
LM_FATAL("could not open config file " << file);
}
/// put the current file to stack
opened_files.push_back(file);
current_line.push_back(0);
opened_ifstreams.push_back(&f);
DUMP("parser state " << Parser::getParserState(), DBG_INFO);
std::string buffer;
bool section_flag = false;
bool found_section = false;
std::string mot;
units_converter.setOutUnits(code_unit_system);
// section_units.push_back(real_unit_system);
while (f.good()) {
Parser::getLine(f, buffer, current_line.back());
DUMP("treat line " << current_line.back(), DBG_DETAIL);
unsigned long found = buffer.find_first_of("#");
std::string buffer_comment_free = buffer.substr(0, found - 1);
buffer = buffer_comment_free;
/* si il s'agit d'un commentaire on ne fait rien */
if (buffer[0] == '#' || buffer == "") {
continue;
}
std::stringstream line(buffer);
try {
Parser::strNext(mot, line);
} catch (LibMultiScaleException &e) {
DUMP("Parser exception " << e.what() << std::endl
<< getParserState(),
DBG_WARNING);
continue;
}
if (!section_flag && mot == "Section") {
Parser::strNext(mot, line);
// search for ":"
size_t pos = mot.find(":");
std::string id;
std::string sec_name;
if (pos != std::string::npos) {
id = mot.substr(pos + 1);
sec_name = mot.substr(0, pos);
} else
sec_name = mot;
if (section_name == sec_name && id == section_id) {
section_flag = true;
found_section = true;
UnitSystem units;
try {
Parser::parse(units, line);
} catch (LibMultiScaleException &e) {
LM_FATAL("unit system was not provided for section " << section_name);
}
section_units.push_back(units);
units_converter.setInUnits(section_units.back());
units_converter.computeConversions();
continue;
}
}
if (section_flag && mot == "endSection") {
section_flag = false;
section_units.pop_back();
if (section_units.size() > 0)
units_converter.setInUnits(section_units.back());
units_converter.computeConversions();
}
if (section_flag) {
substituteVariables(buffer);
UInt result = parseGenericKeywords(buffer, obj);
if (!result)
result = obj.parseLine(buffer);
if (!result)
LM_FATAL("not parsed line " << buffer);
}
}
// if (section_units.back() != real_unit_system)
// LM_FATAL("problem in piling the section units");
if (!found_section)
LM_FATAL("section named " << section_name << " with id " << section_id
<< " is missing");
/// pop the current file from stack
opened_files.pop_back();
current_line.pop_back();
if (section_units.size() > 0)
units_converter.setInUnits(section_units.back());
units_converter.computeConversions();
opened_ifstreams.pop_back();
DUMP("parser state " << opened_files.size() << " " << current_line.size()
<< " " << Parser::getParserState(),
DBG_INFO);
}
/* -------------------------------------------------------------------------- */
void Parser::substituteVariables(std::string &str) {
size_t pos = str.find("${");
while (pos != std::string::npos) {
size_t pos2 = str.find("}", pos);
if (pos2 == std::string::npos)
LM_FATAL("syntax error: unclosed ${ } sequence \n"
<< Parser::getParserState());
std::string varname = str.substr(pos + 2, pos2 - pos - 2);
Real res;
try {
math_parser.parse(varname, res);
} catch (std::string mess) {
LM_FATAL(getParserState() << std::endl
<< "\"" << str << "\"" << std::endl
<< mess);
}
std::stringstream tmp;
tmp << res;
str.replace(pos, pos2 - pos + 1, tmp.str());
pos = str.find("${");
}
pos = str.find("$(");
while (pos != std::string::npos) {
size_t pos2 = str.find(")", pos);
if (pos2 == std::string::npos)
LM_FATAL("syntax error: unclosed $( ) sequence");
std::string varname = str.substr(pos + 2, pos2 - pos - 2);
char *var = lm_getenv(varname.c_str());
if (var != NULL)
str.replace(pos, pos2 - pos + 1, var);
else
LM_FATAL(getParserState()
<< std::endl
<< "\"" << str << "\"" << std::endl
<< "environment variable " << varname << " was not defined");
pos = str.find("$(");
}
}
/* -------------------------------------------------------------------------- */
UInt Parser::parseGenericKeywords(std::string &linebuffer, Parsable &obj) {
std::stringstream line(linebuffer);
std::string mot;
Parser::strNext(mot, line);
if (mot == "LET") {
std::stringstream var_buffer;
try {
while (1) {
std::string mot;
strNext(mot, line);
var_buffer << mot << " ";
}
} catch (LibMultiScaleException &e) {
if (std::string(e.what()) == std::string("unable to parse word")) {
} else {
LM_FATAL(e.what() << std::endl << getParserState());
}
}
try {
Real res;
math_parser.parse(var_buffer.str(), res);
} catch (LibMultiScaleException &e) {
LM_FATAL(e.what() << std::endl
<< " cannot parse algebraic expression "
<< var_buffer.str() << getParserState());
}
return true;
} else if (mot == "PRINT") {
Real value;
if (math_parser.parse(line.str().substr(line.tellg()), value)) {
std::string key;
line >> key;
DUMPFILE(fout, key << " = " << value);
} else
return false;
return true;
} else if (mot == "INCLUDE") {
Parser::strNext(mot, line);
if (mot == "this") {
mot = opened_files.back();
}
std::string section;
try {
strNext(section, line);
} catch (LibMultiScaleException &e) {
LM_FATAL(" Missing section name in line " << current_line.back() << ": '"
<< line.str() << "'"
<< getParserState());
}
try {
std::string id;
strNext(id, line);
parseConfigFile(mot, section, id, obj);
} catch (LibMultiScaleException &e) {
parseConfigFile(mot, section, "", obj);
}
return true;
} else if (mot == "FOR") {
std::string mot;
// save starting point
for_starting_line.push_back(current_line.back() + 1);
Parser::strNext(mot, line);
// read name of the for variable
for_var.push_back(mot);
Parser::strNext(mot, line);
UInt pos = line.tellg();
if (mot != "in" || pos == line.str().length())
LM_FATAL(getParserState() << std::endl
<< "\"" << line.str() << "\"" << std::endl
<< "sytax error in for loop");
// construct the items to iterate
std::string buffer = line.str().substr(pos);
std::stringstream items(buffer);
Parser::strNext(mot, items);
std::list<std::string> item_vec;
if (mot == "range") {
UInt start, end, increment;
parse(start, items);
parse(end, items);
parse(increment, items);
for (UInt i = start; i < end; i += increment) {
std::stringstream sstr;
sstr << i;
item_vec.push_back(sstr.str());
}
} else {
while (!items.fail()) {
item_vec.push_back(mot);
try {
Parser::strNext(mot, items);
} catch (LibMultiScaleException &e) {
}
}
}
for_items.push_back(item_vec);
std::string value;
value = for_items.back().front();
for_items.back().pop_front();
// set the variable to the correct initial value
Real res;
math_parser.parse(for_var.back() + " = " + value, res);
return true;
} else if (mot == "endFOR") {
UInt nb_items_left = for_items.back().size();
// set the variable to the next value
if (nb_items_left == 0) {
// it is the end of the loop then
math_parser.eraseVariable(for_var.back());
for_starting_line.pop_back();
for_items.pop_back();
for_var.pop_back();
} else {
std::string value;
value = for_items.back().front();
for_items.back().pop_front();
DUMPFILE(Parser::fout,
"inside of var loop " << for_var.back()
<< " now takes the value " << value);
// set the variable to the correct initial value
Real res;
math_parser.parse(for_var.back() + " = " + value, res);
// rewind the file to the correct line
rewindToLine(for_starting_line.back());
}
return true;
}
return false;
}
/* -------------------------------------------------------------------------- */
inline std::string Parser::getParserState() {
std::vector<std::string>::iterator it_file = opened_files.begin();
std::vector<std::string>::iterator end_file = opened_files.end();
std::vector<UInt>::iterator it_line = current_line.begin();
std::stringstream res;
while (it_file != end_file) {
res << std::endl << "\t" << *it_file << ":" << *it_line;
++it_file;
++it_line;
}
return res.str();
}
/* -------------------------------------------------------------------------- */
std::map<std::string, double> &Parser::getAlgebraicVariables() {
return math_parser.getVariables();
}
/* -------------------------------------------------------------------------- */
UInt Parser::strNext(std::string &str, std::stringstream &line) {
UInt word_counter = 0;
line >> str;
if (line.fail())
LM_THROW("unable to parse word");
++word_counter;
if (str[0] == '"') {
str = str.substr(1);
unsigned long found = str.find_first_of("\"");
while (found == std::string::npos) {
UInt pos = line.tellg();
if (pos < line.str().length()) {
std::string tmp_str;
line >> tmp_str;
if (line.fail())
LM_THROW("unable to parse word");
++word_counter;
str += " " + tmp_str;
found = str.find_first_of("\"");
} else
LM_FATAL("unterminated quoted sequence");
}
if (found != str.size() - 1)
LM_FATAL("quotes must be followed by a whitespace");
str = str.substr(0, found);
}
return word_counter;
}
/* -------------------------------------------------------------------------- */
void Parser::shiftLine(const ParseResult &parsed, std::stringstream &line) {
std::string buf;
for (UInt i = 0; i < parsed.nb_word_parsed; ++i) {
line >> buf;
if (line.fail())
LM_THROW("unable to shift " << parsed.nb_word_parsed << " words");
}
}
/* -------------------------------------------------------------------------- */
UInt _parse(std::map<std::string, ArgumentContainer *> &inputs,
std::stringstream &line, UInt n_entries) {
std::string buffer;
std::string component_name;
std::string output_name;
std::string input_name;
UInt nb = Parser::strNext(buffer, line);
auto pos = buffer.find("=");
if (pos != std::string::npos) {
input_name = buffer.substr(0, pos);
component_name = buffer.substr(pos + 1);
} else {
input_name = "input1";
component_name = buffer;
}
pos = component_name.find(".");
if (pos != std::string::npos) {
output_name = component_name.substr(pos + 1);
component_name = component_name.substr(0, pos);
} else {
output_name = "output";
}
DUMP(input_name << " " << component_name << " " << output_name, DBG_DETAIL);
auto connect = [&](auto &manager) {
auto &component = manager.getObject(component_name);
auto search = inputs.find(input_name);
if (search == inputs.end()) {
DUMP(input_name + ": input not existing", DBG_MESSAGE);
if (inputs.size() > 0) {
DUMP("Possible inputs are:", DBG_MESSAGE);
for (auto p : inputs) {
DUMP("\t" + p.first + "\n", DBG_MESSAGE);
}
} else {
DUMP("there are no possible inputs", DBG_MESSAGE);
}
LM_FATAL("abort:" + input_name + ": input not existing");
}
inputs[input_name] = &component.getOutput(output_name);
};
try {
connect(DomainMultiScale::getManager());
} catch (UnknownID &e) {
try {
connect(FilterManager::getManager());
} catch (LibMultiScaleException &e) {
LM_THROW("id " << input_name << " is most probably not a valid input "
<< std::endl
<< e.what());
}
}
return nb;
}
/* -------------------------------------------------------------------------- */
/// static instanciation
/* -------------------------------------------------------------------------- */
UnitsConverter Parser::units_converter;
std::vector<UnitSystem> Parser::section_units;
AlgebraicExpressionParser Parser::math_parser;
std::ofstream Parser::fout("log.parser", std::ios_base::out);
std::vector<std::string> Parser::opened_files;
std::vector<UInt> Parser::current_line;
std::vector<std::ifstream *> Parser::opened_ifstreams;
std::vector<UInt> Parser::for_starting_line;
std::vector<std::list<std::string>> Parser::for_items;
std::vector<std::string> Parser::for_var;
__END_LIBMULTISCALE__

Event Timeline