mirror of
https://github.com/OPM/ResInsight.git
synced 2024-12-28 18:01:08 -06:00
#7316 Curve Calculator: Add support for single line if-statement
This commit is contained in:
parent
1a8f36373c
commit
a060ba349e
@ -308,7 +308,7 @@ bool RimSummaryCalculation::calculate()
|
||||
parser.assignVector( leftHandSideVariableName, resultValues );
|
||||
|
||||
QString errorText;
|
||||
bool evaluatedOk = parser.evaluate( m_expression, &errorText );
|
||||
bool evaluatedOk = parser.expandIfStatementsAndEvaluate( m_expression, &errorText );
|
||||
|
||||
if ( evaluatedOk )
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "RimSummaryCalculation.h"
|
||||
|
||||
#include "ExpressionParserImpl.h"
|
||||
#include "expressionparser/ExpressionParser.h"
|
||||
|
||||
#include <numeric>
|
||||
@ -75,3 +76,87 @@ TEST( RicExpressionParserTest, FindLeftHandSide )
|
||||
EXPECT_STREQ( s.toStdString().data(), "c" );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RicExpressionParserTest, ForLoopWithIfStatement )
|
||||
{
|
||||
std::vector<double> a( 10 );
|
||||
std::iota( a.begin(), a.end(), 10 );
|
||||
|
||||
std::vector<double> b( 10 );
|
||||
std::iota( b.begin(), b.end(), 100 );
|
||||
|
||||
std::vector<double> c( 10 );
|
||||
|
||||
ExpressionParser parser;
|
||||
parser.assignVector( "a", a );
|
||||
parser.assignVector( "b", b );
|
||||
parser.assignVector( "c", c );
|
||||
|
||||
QString expr = "for (var i := 0; i < min(a[],b[],c[]); i += 1)\n"
|
||||
"{ \n"
|
||||
" c[i] := if((a[i] > 13), a[i], b[i]); \n"
|
||||
"} \n";
|
||||
|
||||
EXPECT_TRUE( parser.evaluate( expr ) );
|
||||
|
||||
EXPECT_DOUBLE_EQ( c[0], 100.0 );
|
||||
EXPECT_DOUBLE_EQ( c[9], 19.0 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RicExpressionParserTest, ExpandedIfStatement )
|
||||
{
|
||||
std::vector<double> a( 10 );
|
||||
std::iota( a.begin(), a.end(), 10 );
|
||||
|
||||
std::vector<double> b( 10 );
|
||||
std::iota( b.begin(), b.end(), 100 );
|
||||
|
||||
std::vector<double> c( 10 );
|
||||
|
||||
ExpressionParser parser;
|
||||
parser.assignVector( "a", a );
|
||||
parser.assignVector( "b", b );
|
||||
parser.assignVector( "c", c );
|
||||
|
||||
QString expr = "c := if((a > 13), a, b)";
|
||||
auto expandedText = ExpressionParserImpl::expandIfStatements( expr );
|
||||
|
||||
// std::cout << expandedText.toStdString();
|
||||
|
||||
EXPECT_TRUE( parser.evaluate( expandedText ) );
|
||||
|
||||
EXPECT_DOUBLE_EQ( c[0], 100.0 );
|
||||
EXPECT_DOUBLE_EQ( c[9], 19.0 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RicExpressionParserTest, ExpandIfStatementsAndEvaluate )
|
||||
{
|
||||
std::vector<double> a( 10 );
|
||||
std::iota( a.begin(), a.end(), 10 );
|
||||
|
||||
std::vector<double> b( 10 );
|
||||
std::iota( b.begin(), b.end(), 100 );
|
||||
|
||||
std::vector<double> c( 10 );
|
||||
|
||||
ExpressionParser parser;
|
||||
parser.assignVector( "a", a );
|
||||
parser.assignVector( "b", b );
|
||||
parser.assignVector( "c", c );
|
||||
|
||||
QString expr = "c := if((a > 13), a, b)";
|
||||
|
||||
EXPECT_TRUE( parser.expandIfStatementsAndEvaluate( expr ) );
|
||||
|
||||
EXPECT_DOUBLE_EQ( c[0], 100.0 );
|
||||
EXPECT_DOUBLE_EQ( c[9], 19.0 );
|
||||
}
|
||||
|
18
ThirdParty/expressionparser/ExpressionParser.cpp
vendored
18
ThirdParty/expressionparser/ExpressionParser.cpp
vendored
@ -59,3 +59,21 @@ bool ExpressionParser::evaluate(const QString& expressionText, QString* errorTex
|
||||
{
|
||||
return m_expressionParserImpl->evaluate(expressionText, errorText);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool ExpressionParser::expandIfStatementsAndEvaluate(const QString& expressionText, QString* errorText /*= nullptr*/)
|
||||
{
|
||||
if (expressionText.contains("if"))
|
||||
{
|
||||
QString expandedExpressionText = ExpressionParserImpl::expandIfStatements(expressionText);
|
||||
|
||||
return m_expressionParserImpl->evaluate(expandedExpressionText, errorText);
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_expressionParserImpl->evaluate(expressionText, errorText);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
|
||||
void assignVector(const QString& variableName, std::vector<double>& vector);
|
||||
bool evaluate(const QString& expressionText, QString* errorText = nullptr);
|
||||
bool expandIfStatementsAndEvaluate(const QString& expressionText, QString* errorText = nullptr);
|
||||
|
||||
private:
|
||||
std::unique_ptr<ExpressionParserImpl> m_expressionParserImpl;
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include "ExpressionParserImpl.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -123,3 +125,52 @@ QString ExpressionParserImpl::parserErrorText(parser_t& parser)
|
||||
|
||||
return txt;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// The parser do not support single-line if statements on a vector.
|
||||
// Expand a single line if-statement to a for loop over all items in the referenced
|
||||
// vectors. The script will add '[i]' as postfix to all variables, assuming all variables
|
||||
// to be vectors. This statement will be put in a for loop over all elements counting
|
||||
// up to size of the vector with minimum items.
|
||||
//
|
||||
// Single line statement :
|
||||
// c := if((a > 13), a, b)
|
||||
//
|
||||
// Intended parser script text
|
||||
//
|
||||
// for (var i : = 0; i < min(c[], a[], b[]); i += 1)
|
||||
// {
|
||||
// c[i] : = if ((a[i] > 13), a[i], b[i]);
|
||||
// }
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString ExpressionParserImpl::expandIfStatements(const QString& expressionText)
|
||||
{
|
||||
QString expandedText;
|
||||
{
|
||||
QString textWithVectorBrackets = expressionText;
|
||||
|
||||
QString listOfVars;
|
||||
auto allVectorVariables = detectReferencedVariables(expressionText);
|
||||
for (const QString& var : allVectorVariables)
|
||||
{
|
||||
listOfVars += QString("%1[],").arg(var);
|
||||
|
||||
QString regexpText = QString("\\b%1\\b").arg(var);
|
||||
QRegularExpression regexp(regexpText);
|
||||
|
||||
QString varWithBrackets = var + "[i]";
|
||||
textWithVectorBrackets = textWithVectorBrackets.replace(regexp, varWithBrackets);
|
||||
}
|
||||
|
||||
listOfVars = listOfVars.left(listOfVars.size() - 1);
|
||||
|
||||
expandedText = QString("for (var i := 0; i < min(%1); i += 1)\n").arg(listOfVars);
|
||||
expandedText += "{\n";
|
||||
expandedText += QString(" %1;\n").arg(textWithVectorBrackets);
|
||||
expandedText += "}\n";
|
||||
}
|
||||
|
||||
return expandedText;
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ public:
|
||||
|
||||
void assignVector(const QString& variableName, std::vector<double>& vector);
|
||||
bool evaluate(const QString& expressionText, QString* errorText = nullptr);
|
||||
|
||||
static QString expandIfStatements(const QString& expressionText);
|
||||
|
||||
private:
|
||||
QString parserErrorText(parser_t& parser);
|
||||
|
Loading…
Reference in New Issue
Block a user