Files
opm-common/opm/parser/eclipse/Parser/Parser.cpp
Joakim Hove abd0905171 Changed parser to support parsing of keywords with wildcard like
"TVDP*". An importtant change is that we now query the parser
canParseKeyword() instead of hasKeyword().
2013-12-01 09:28:14 +01:00

302 lines
11 KiB
C++

/*
Copyright 2013 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <boost/filesystem.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/Parser/ParserKeyword.hpp>
#include <opm/parser/eclipse/RawDeck/RawConsts.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Deck/DeckIntItem.hpp>
namespace Opm {
Parser::Parser(bool addDefault) {
if (addDefault)
addDefaultKeywords();
}
DeckPtr Parser::parse(const std::string &dataFile) const {
return parse(dataFile, true);
}
/*
About INCLUDE: Observe that the ECLIPSE parser is slightly unlogical
when it comes to nested includes; the path to an included file is always
interpreted relative to the filesystem location of the DATA file, and
not the location of the file issuing the INCLUDE command. That behaviour
is retained in the current implementation.
*/
DeckPtr Parser::parse(const std::string &dataFileName, bool strictParsing) const {
DeckPtr deck(new Deck());
boost::filesystem::path dataFile(dataFileName);
boost::filesystem::path rootPath;
if (dataFile.is_absolute())
rootPath = dataFile.parent_path();
else
rootPath = boost::filesystem::current_path() / dataFile.parent_path();
parseFile(deck, dataFile, rootPath , strictParsing);
return deck;
}
size_t Parser::size() const {
return m_parserKeywords.size();
}
void Parser::addKeyword(ParserKeywordConstPtr parserKeyword) {
const std::string& name = parserKeyword->getName();
dropKeyword( name );
m_parserKeywords.insert(std::make_pair(name, parserKeyword));
if (ParserKeyword::wildCardName(name))
m_wildCardKeywords.insert( std::make_pair(name , parserKeyword ));
}
ParserKeywordConstPtr Parser::matchingKeyword(const std::string& name) const {
std::map<std::string, ParserKeywordConstPtr>::const_iterator iter = m_wildCardKeywords.begin();
ParserKeywordConstPtr keyword;
while (true) {
if (iter == m_wildCardKeywords.end())
break;
if ((*iter).second->matches(name)) {
keyword = (*iter).second;
break;
}
++iter;
}
return keyword;
}
bool Parser::hasKeyword(const std::string& keyword) const {
return (m_parserKeywords.find(keyword) != m_parserKeywords.end());
}
bool Parser::hasWildCardKeyword(const std::string& keyword) const {
return (m_wildCardKeywords.find(keyword) != m_parserKeywords.end());
}
bool Parser::canParseKeyword( const std::string& keyword) const {
if (hasKeyword(keyword))
return true;
else {
ParserKeywordConstPtr wildCardKeyword = matchingKeyword( keyword );
if (wildCardKeyword)
return true;
else
return false;
}
}
bool Parser::dropKeyword(const std::string& keyword) {
bool erase = (m_parserKeywords.erase( keyword ) == 1);
if (erase)
m_wildCardKeywords.erase( keyword );
return erase;
}
ParserKeywordConstPtr Parser::getKeyword(const std::string& keyword) const {
if (hasKeyword(keyword)) {
return m_parserKeywords.at(keyword);
} else {
ParserKeywordConstPtr wildCardKeyword = matchingKeyword( keyword );
if (wildCardKeyword)
return wildCardKeyword;
else
throw std::invalid_argument("Do not have parser keyword for parsing: " + keyword);
}
}
void Parser::parseFile(DeckPtr deck, const boost::filesystem::path& file, const boost::filesystem::path& rootPath, bool parseStrict) const {
bool verbose = false;
std::ifstream inputstream;
size_t lineNR = 0;
inputstream.open(file.string().c_str());
if (inputstream) {
RawKeywordPtr rawKeyword;
while (tryParseKeyword(deck, file.string() , lineNR , inputstream, rawKeyword, parseStrict)) {
if (rawKeyword->getKeywordName() == Opm::RawConsts::include) {
RawRecordConstPtr firstRecord = rawKeyword->getRecord(0);
std::string includeFileString = firstRecord->getItem(0);
boost::filesystem::path includeFile(includeFileString);
if (includeFile.is_relative())
includeFile = rootPath / includeFile;
if (verbose)
std::cout << rawKeyword->getKeywordName() << " " << includeFile << std::endl;
parseFile(deck, includeFile, rootPath , parseStrict);
} else {
if (verbose)
std::cout << rawKeyword->getKeywordName() << std::endl;
if (canParseKeyword(rawKeyword->getKeywordName())) {
ParserKeywordConstPtr parserKeyword = getKeyword(rawKeyword->getKeywordName());
ParserKeywordActionEnum action = parserKeyword->getAction();
if (action == INTERNALIZE) {
DeckKeywordPtr deckKeyword = parserKeyword->parse(rawKeyword);
deck->addKeyword(deckKeyword);
} else if (action == IGNORE_WARNING)
deck->addWarning( "The keyword " + rawKeyword->getKeywordName() + " is ignored - this might potentially affect the results" , file.string() , rawKeyword->getLineNR());
} else {
DeckKeywordPtr deckKeyword(new DeckKeyword(rawKeyword->getKeywordName(), false));
deck->addKeyword(deckKeyword);
deck->addWarning( "The keyword " + rawKeyword->getKeywordName() + " is not recognized" , file.string() , lineNR);
}
}
rawKeyword.reset();
}
inputstream.close();
} else
throw std::invalid_argument("Failed to open file: " + file.string());
}
void Parser::loadKeywords(const Json::JsonObject& jsonKeywords) {
if (jsonKeywords.is_array()) {
for (size_t index = 0; index < jsonKeywords.size(); index++) {
Json::JsonObject jsonKeyword = jsonKeywords.get_array_item(index);
ParserKeywordConstPtr parserKeyword(new ParserKeyword(jsonKeyword));
addKeyword(parserKeyword);
}
} else
throw std::invalid_argument("Input JSON object is not an array");
}
RawKeywordPtr Parser::createRawKeyword(const DeckConstPtr deck, const std::string& filename , size_t lineNR , const std::string& keywordString, bool strictParsing) const {
if (canParseKeyword(keywordString)) {
ParserKeywordConstPtr parserKeyword = getKeyword( keywordString );
ParserKeywordActionEnum action = parserKeyword->getAction();
if (action == THROW_EXCEPTION)
throw std::invalid_argument("Parsing terminated by fatal keyword: " + keywordString);
if (parserKeyword->getSizeType() == SLASH_TERMINATED)
return RawKeywordPtr(new RawKeyword(keywordString , filename , lineNR));
else {
size_t targetSize;
if (parserKeyword->hasFixedSize())
targetSize = parserKeyword->getFixedSize();
else {
const std::pair<std::string, std::string> sizeKeyword = parserKeyword->getSizeDefinitionPair();
DeckKeywordConstPtr sizeDefinitionKeyword = deck->getKeyword(sizeKeyword.first);
DeckItemConstPtr sizeDefinitionItem;
{
DeckRecordConstPtr record = sizeDefinitionKeyword->getRecord(0);
sizeDefinitionItem = record->getItem(sizeKeyword.second);
}
targetSize = sizeDefinitionItem->getInt(0);
}
return RawKeywordPtr(new RawKeyword(keywordString, filename , lineNR , targetSize , parserKeyword->isTableCollection()));
}
} else {
if (strictParsing) {
throw std::invalid_argument("Keyword " + keywordString + " not recognized ");
} else {
return RawKeywordPtr(new RawKeyword(keywordString, filename , lineNR , 0));
}
}
}
bool Parser::tryParseKeyword(const DeckConstPtr deck, const std::string& filename , size_t& lineNR , std::ifstream& inputstream, RawKeywordPtr& rawKeyword, bool strictParsing) const {
std::string line;
std::cout << "tryParse " << std::endl;
while (std::getline(inputstream, line)) {
std::string keywordString;
lineNR++;
if (rawKeyword == NULL) {
if (RawKeyword::tryParseKeyword(line, keywordString)) {
rawKeyword = createRawKeyword(deck, filename , lineNR , keywordString, strictParsing);
}
} else {
if (RawKeyword::useLine(line)) {
rawKeyword->addRawRecordString(line);
}
}
if (rawKeyword != NULL && rawKeyword->isFinished())
return true;
}
return false;
}
bool Parser::loadKeywordFromFile(const boost::filesystem::path& configFile) {
try {
Json::JsonObject jsonKeyword(configFile);
ParserKeywordConstPtr parserKeyword(new ParserKeyword(jsonKeyword));
addKeyword(parserKeyword);
return true;
}
catch (...) {
return false;
}
}
void Parser::loadKeywordsFromDirectory(const boost::filesystem::path& directory, bool recursive, bool onlyALLCAPS8) {
if (!boost::filesystem::exists(directory))
throw std::invalid_argument("Directory: " + directory.string() + " does not exist.");
else {
boost::filesystem::directory_iterator end;
for (boost::filesystem::directory_iterator iter(directory); iter != end; iter++) {
if (boost::filesystem::is_directory(*iter)) {
if (recursive)
loadKeywordsFromDirectory(*iter, recursive, onlyALLCAPS8);
} else {
if (ParserKeyword::validName(iter->path().filename().string()) || !onlyALLCAPS8) {
if (!loadKeywordFromFile(*iter))
std::cerr << "** Warning: failed to load keyword from file:" << iter->path() << std::endl;
}
}
}
}
}
} // namespace Opm