mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#7316 Curve Calculator: Add support for single line if-statement
This commit is contained in:
@@ -308,7 +308,7 @@ bool RimSummaryCalculation::calculate()
|
|||||||
parser.assignVector( leftHandSideVariableName, resultValues );
|
parser.assignVector( leftHandSideVariableName, resultValues );
|
||||||
|
|
||||||
QString errorText;
|
QString errorText;
|
||||||
bool evaluatedOk = parser.evaluate( m_expression, &errorText );
|
bool evaluatedOk = parser.expandIfStatementsAndEvaluate( m_expression, &errorText );
|
||||||
|
|
||||||
if ( evaluatedOk )
|
if ( evaluatedOk )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "RimSummaryCalculation.h"
|
#include "RimSummaryCalculation.h"
|
||||||
|
|
||||||
|
#include "ExpressionParserImpl.h"
|
||||||
#include "expressionparser/ExpressionParser.h"
|
#include "expressionparser/ExpressionParser.h"
|
||||||
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
@@ -75,3 +76,87 @@ TEST( RicExpressionParserTest, FindLeftHandSide )
|
|||||||
EXPECT_STREQ( s.toStdString().data(), "c" );
|
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);
|
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);
|
void assignVector(const QString& variableName, std::vector<double>& vector);
|
||||||
bool evaluate(const QString& expressionText, QString* errorText = nullptr);
|
bool evaluate(const QString& expressionText, QString* errorText = nullptr);
|
||||||
|
bool expandIfStatementsAndEvaluate(const QString& expressionText, QString* errorText = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<ExpressionParserImpl> m_expressionParserImpl;
|
std::unique_ptr<ExpressionParserImpl> m_expressionParserImpl;
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include "ExpressionParserImpl.h"
|
#include "ExpressionParserImpl.h"
|
||||||
|
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@@ -123,3 +125,52 @@ QString ExpressionParserImpl::parserErrorText(parser_t& parser)
|
|||||||
|
|
||||||
return txt;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ public:
|
|||||||
void assignVector(const QString& variableName, std::vector<double>& vector);
|
void assignVector(const QString& variableName, std::vector<double>& vector);
|
||||||
bool evaluate(const QString& expressionText, QString* errorText = nullptr);
|
bool evaluate(const QString& expressionText, QString* errorText = nullptr);
|
||||||
|
|
||||||
|
static QString expandIfStatements(const QString& expressionText);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString parserErrorText(parser_t& parser);
|
QString parserErrorText(parser_t& parser);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user