From 65b629e423223ef926655910307985cced806ec7 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Mon, 4 Feb 2019 15:59:09 +0100 Subject: [PATCH] Add ParseContext::PARSE_LONG_KEYWORD The ParserContext error mode PARSE_LONG_KEYWORD is used to handle keywords longer than 8 characters. The lenient option is to only consider the first 8 characters. --- opm/parser/eclipse/Parser/ParseContext.hpp | 7 ++ .../parser/eclipse/Parser/ParseContext.cpp | 2 + src/opm/parser/eclipse/Parser/Parser.cpp | 91 +++++++++++-------- .../parser/eclipse/Parser/ParserKeyword.cpp | 9 +- tests/parser/ParseContextTests.cpp | 20 ++++ tests/parser/ParserTests.cpp | 3 - 6 files changed, 84 insertions(+), 48 deletions(-) diff --git a/opm/parser/eclipse/Parser/ParseContext.hpp b/opm/parser/eclipse/Parser/ParseContext.hpp index 9e72d3707..dc1838c73 100644 --- a/opm/parser/eclipse/Parser/ParseContext.hpp +++ b/opm/parser/eclipse/Parser/ParseContext.hpp @@ -195,6 +195,13 @@ namespace Opm { const static std::string PARSE_MISSING_INCLUDE; + /* + Should we allow keywords of length more than eight characters? If the + keyword is too long it will be internalized using only the eight first + characters. + */ + const static std::string PARSE_LONG_KEYWORD; + /* Some property modfiers can be modified in the Schedule section; this effectively means that Eclipse supports time diff --git a/src/opm/parser/eclipse/Parser/ParseContext.cpp b/src/opm/parser/eclipse/Parser/ParseContext.cpp index 35006856c..b788f0b08 100644 --- a/src/opm/parser/eclipse/Parser/ParseContext.cpp +++ b/src/opm/parser/eclipse/Parser/ParseContext.cpp @@ -77,6 +77,7 @@ namespace Opm { addKey(PARSE_MISSING_DIMS_KEYWORD, InputError::THROW_EXCEPTION); addKey(PARSE_EXTRA_DATA, InputError::THROW_EXCEPTION); addKey(PARSE_MISSING_INCLUDE, InputError::EXIT1); + addKey(PARSE_LONG_KEYWORD, InputError::WARN); addKey(UNSUPPORTED_SCHEDULE_GEO_MODIFIER, InputError::THROW_EXCEPTION); addKey(UNSUPPORTED_COMPORD_TYPE, InputError::THROW_EXCEPTION); @@ -298,6 +299,7 @@ namespace Opm { const std::string ParseContext::PARSE_EXTRA_DATA = "PARSE_EXTRA_DATA"; const std::string ParseContext::PARSE_MISSING_SECTIONS = "PARSE_MISSING_SECTIONS"; const std::string ParseContext::PARSE_MISSING_INCLUDE = "PARSE_MISSING_INCLUDE"; + const std::string ParseContext::PARSE_LONG_KEYWORD = "PARSE_LONG_KEYWORD"; const std::string ParseContext::UNSUPPORTED_SCHEDULE_GEO_MODIFIER = "UNSUPPORTED_SCHEDULE_GEO_MODIFIER"; const std::string ParseContext::UNSUPPORTED_COMPORD_TYPE = "UNSUPPORTED_COMPORD_TYPE"; diff --git a/src/opm/parser/eclipse/Parser/Parser.cpp b/src/opm/parser/eclipse/Parser/Parser.cpp index a962327b8..b3ffc9ad5 100644 --- a/src/opm/parser/eclipse/Parser/Parser.cpp +++ b/src/opm/parser/eclipse/Parser/Parser.cpp @@ -417,44 +417,26 @@ void ParserState::addPathAlias( const std::string& alias, const std::string& pat this->pathMap.emplace( alias, path ); } -std::shared_ptr< RawKeyword > createRawKeyword( const string_view& kw, ParserState& parserState, const Parser& parser ) { - auto keywordString = ParserKeyword::getDeckName( kw ); - if( !parser.isRecognizedKeyword( keywordString ) ) { - if( ParserKeyword::validDeckName( keywordString ) ) { - std::string msg = "Keyword " + keywordString + " not recognized."; - parserState.parseContext.handleUnknownKeyword( keywordString.string(), parserState.errors ); - parserState.unknown_keyword = true; - return {}; - } - - if (!parserState.unknown_keyword) - parserState.handleRandomText( keywordString ); - - return {}; - } - parserState.unknown_keyword = false; - - - const auto* parserKeyword = parser.getParserKeywordFromDeckName( keywordString ); +std::shared_ptr createRawKeyword(const ParserKeyword* parserKeyword, const std::string& keywordString, ParserState& parserState, const Parser& parser) { if( parserKeyword->getSizeType() == SLASH_TERMINATED || parserKeyword->getSizeType() == UNKNOWN) { const auto rawSizeType = parserKeyword->getSizeType() == SLASH_TERMINATED - ? Raw::SLASH_TERMINATED - : Raw::UNKNOWN; + ? Raw::SLASH_TERMINATED + : Raw::UNKNOWN; return std::make_shared< RawKeyword >( keywordString, rawSizeType, - parserState.current_path().string(), - parserState.line() ); + parserState.current_path().string(), + parserState.line() ); } if( parserKeyword->hasFixedSize() ) { return std::make_shared< RawKeyword >( keywordString, - parserState.current_path().string(), - parserState.line(), - parserKeyword->getFixedSize(), - parserKeyword->isTableCollection() ); + parserState.current_path().string(), + parserState.line(), + parserKeyword->getFixedSize(), + parserKeyword->isTableCollection() ); } const auto& keyword_size = parserKeyword->getKeywordSize(); @@ -465,14 +447,14 @@ std::shared_ptr< RawKeyword > createRawKeyword( const string_view& kw, ParserSta const auto& record = sizeDefinitionKeyword.getRecord(0); const auto targetSize = record.getItem( keyword_size.item ).get< int >( 0 ) + keyword_size.shift; return std::make_shared< RawKeyword >( keywordString, - parserState.current_path().string(), - parserState.line(), - targetSize, - parserKeyword->isTableCollection() ); + parserState.current_path().string(), + parserState.line(), + targetSize, + parserKeyword->isTableCollection() ); } - std::string msg = "Expected the kewyord: " +keyword_size.keyword - + " to infer the number of records in: " + keywordString; + std::string msg = "Expected the kewyord: " +keyword_size.keyword + + " to infer the number of records in: " + keywordString; parserState.parseContext.handleError(ParseContext::PARSE_MISSING_DIMS_KEYWORD , msg, parserState.errors ); const auto* keyword = parser.getKeyword( keyword_size.keyword ); @@ -481,12 +463,47 @@ std::shared_ptr< RawKeyword > createRawKeyword( const string_view& kw, ParserSta const auto targetSize = int_item.getDefault< int >( ) + keyword_size.shift; return std::make_shared< RawKeyword >( keywordString, - parserState.current_path().string(), - parserState.line(), - targetSize, - parserKeyword->isTableCollection() ); + parserState.current_path().string(), + parserState.line(), + targetSize, + parserKeyword->isTableCollection() ); } + +std::shared_ptr< RawKeyword > createRawKeyword( const string_view& kw, ParserState& parserState, const Parser& parser ) { + auto keywordString = ParserKeyword::getDeckName( kw ); + + if (parser.isRecognizedKeyword(keywordString)) { + parserState.unknown_keyword = false; + const auto* parserKeyword = parser.getParserKeywordFromDeckName( keywordString.string() ); + return createRawKeyword(parserKeyword, keywordString.string(), parserState, parser); + } + + if (keywordString.size() > RawConsts::maxKeywordLength) { + const std::string keyword8 = {keywordString.begin() , keywordString.begin() + RawConsts::maxKeywordLength}; + if (parser.isRecognizedKeyword(keyword8)) { + std::string msg = "Keyword: " + keywordString.string() + " too long - only first eight characters recognized"; + parserState.parseContext.handleError(ParseContext::PARSE_LONG_KEYWORD, msg, parserState.errors); + + parserState.unknown_keyword = false; + const auto* parserKeyword = parser.getParserKeywordFromDeckName( keyword8 ); + return createRawKeyword(parserKeyword, keyword8, parserState, parser); + } + } + + if( ParserKeyword::validDeckName( keywordString ) ) { + parserState.parseContext.handleUnknownKeyword( keywordString.string(), parserState.errors ); + parserState.unknown_keyword = true; + return {}; + } + + if (!parserState.unknown_keyword) + parserState.handleRandomText( keywordString ); + + return {}; +} + + bool tryParseKeyword( ParserState& parserState, const Parser& parser ) { if (parserState.nextKeyword.length() > 0) { parserState.rawKeyword = createRawKeyword( parserState.nextKeyword, parserState, parser ); diff --git a/src/opm/parser/eclipse/Parser/ParserKeyword.cpp b/src/opm/parser/eclipse/Parser/ParserKeyword.cpp index 39fead42f..6e8ec8992 100644 --- a/src/opm/parser/eclipse/Parser/ParserKeyword.cpp +++ b/src/opm/parser/eclipse/Parser/ParserKeyword.cpp @@ -207,9 +207,6 @@ namespace Opm { bool ParserKeyword::validNameStart( const string_view& name) { - if (name.length() > ParserConst::maxKeywordLength) - return false; - if (!isalpha(name[0])) return false; @@ -228,12 +225,8 @@ namespace Opm { string_view ParserKeyword::getDeckName( const string_view& str ) { auto first_sep = std::find_if( str.begin(), str.end(), RawConsts::is_separator() ); + return { str.begin(), first_sep }; - // only look at the first 8 characters (at most) - if( std::distance( str.begin(), first_sep ) < 9 ) - return { str.begin(), first_sep }; - - return { str.begin(), str.begin() + 9 }; } bool ParserKeyword::validDeckName( const string_view& name) { diff --git a/tests/parser/ParseContextTests.cpp b/tests/parser/ParseContextTests.cpp index e1695e71f..aac700f56 100644 --- a/tests/parser/ParseContextTests.cpp +++ b/tests/parser/ParseContextTests.cpp @@ -769,3 +769,23 @@ BOOST_AUTO_TEST_CASE(Test_ERRORGUARD) { eg.clear(); BOOST_CHECK(!eg); } + + + + + +BOOST_AUTO_TEST_CASE(LONG_KEYWORDS) { + const std::string deck_string = R"( +RPTRUNSPEC +)"; + Parser parser; + ParseContext context; + ErrorGuard error; + + context.update(ParseContext::PARSE_LONG_KEYWORD, InputError::IGNORE); + auto deck = parser.parseString(deck_string, context, error); + BOOST_CHECK( deck.hasKeyword("RPTRUNSP") ); + + context.update(ParseContext::PARSE_LONG_KEYWORD, InputError::THROW_EXCEPTION); + BOOST_CHECK_THROW( parser.parseString(deck_string, context, error), std::invalid_argument); +} diff --git a/tests/parser/ParserTests.cpp b/tests/parser/ParserTests.cpp index 636ce20fc..df7ced2d7 100644 --- a/tests/parser/ParserTests.cpp +++ b/tests/parser/ParserTests.cpp @@ -278,7 +278,6 @@ BOOST_AUTO_TEST_CASE(WildCardTest) { BOOST_CHECK(!parser.isRecognizedKeyword("TVDP*")); BOOST_CHECK(!parser.isRecognizedKeyword("TVDP")); BOOST_CHECK(parser.isRecognizedKeyword("TVDPXXX")); - BOOST_CHECK(!parser.isRecognizedKeyword("TVDPIAMTOOLONG")); BOOST_CHECK(!parser.isRecognizedKeyword("TVD")); BOOST_CHECK(!parser.isRecognizedKeyword("TVDP")); @@ -1327,7 +1326,6 @@ BOOST_AUTO_TEST_CASE(ParserKeyword_withOtherSize_SizeTypeOTHER) { BOOST_AUTO_TEST_CASE(ParserKeyword_validDeckName) { BOOST_CHECK_EQUAL( true , ParserKeyword::validDeckName("SUMMARY")); BOOST_CHECK_EQUAL( true , ParserKeyword::validDeckName("MixeCase")); - BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("NAMETOOLONG")); BOOST_CHECK_EQUAL( true , ParserKeyword::validDeckName("STRING88")); BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("88STRING")); BOOST_CHECK_EQUAL( false , ParserKeyword::validDeckName("KEY.EXT")); @@ -1368,7 +1366,6 @@ BOOST_AUTO_TEST_CASE(ParserKeywordMatches) { BOOST_CHECK_EQUAL( false , parserKeyword->matches("WORLD")); BOOST_CHECK_EQUAL( true , parserKeyword->matches("WORLDABC")); BOOST_CHECK_EQUAL( false , parserKeyword->matches("WORLD#BC")); - BOOST_CHECK_EQUAL( false , parserKeyword->matches("WORLDIAMTOOLONG")); } BOOST_AUTO_TEST_CASE(AddDataKeyword_correctlyConfigured) {