[fix #11475] expressions: add left and right associavity for dump of binary operators

complete test for left associativity
This commit is contained in:
Denis Rouzaud 2014-12-11 14:04:44 +01:00 committed by Matthias Kuhn
parent 0bf1135244
commit a518e9f639
4 changed files with 81 additions and 2 deletions

View File

@ -378,6 +378,8 @@ class QgsExpression
virtual void accept( QgsExpression::Visitor& v ) const;
int precedence() const;
bool leftAssociative() const;
bool rightAssociative() const;
};
class NodeInOperator : QgsExpression::Node

View File

@ -2540,15 +2540,87 @@ int QgsExpression::NodeBinaryOperator::precedence() const
return -1;
}
bool QgsExpression::NodeBinaryOperator::leftAssociative() const
{
// see left/right in qgsexpressionparser.yy
switch ( mOp )
{
case boOr:
case boAnd:
case boEQ:
case boNE:
case boLE:
case boGE:
case boLT:
case boGT:
case boRegexp:
case boLike:
case boILike:
case boNotLike:
case boNotILike:
case boIs:
case boIsNot:
case boPlus:
case boMinus:
case boMul:
case boDiv:
case boIntDiv:
case boMod:
case boConcat:
return true;
case boPow:
return false;
}
Q_ASSERT( 0 && "unexpected binary operator" );
return -1;
}
bool QgsExpression::NodeBinaryOperator::rightAssociative() const
{
// see left/right in qgsexpressionparser.yy
switch ( mOp )
{
case boOr:
case boAnd:
case boEQ:
case boNE:
case boLE:
case boGE:
case boLT:
case boGT:
case boRegexp:
case boLike:
case boILike:
case boNotLike:
case boNotILike:
case boIs:
case boIsNot:
case boPlus:
case boMul:
case boMod:
case boConcat:
case boPow:
return true;
case boMinus:
case boDiv:
case boIntDiv:
return false;
}
Q_ASSERT( 0 && "unexpected binary operator" );
return -1;
}
QString QgsExpression::NodeBinaryOperator::dump() const
{
QgsExpression::NodeBinaryOperator *lOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpLeft );
QgsExpression::NodeBinaryOperator *rOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpRight );
QString fmt;
fmt += lOp && lOp->precedence() < precedence() ? "(%1)" : "%1";
fmt += lOp && ( lOp->precedence() < precedence() || !lOp->leftAssociative() ) ? "(%1)" : "%1";
fmt += " %2 ";
fmt += rOp && rOp->precedence() <= precedence() ? "(%3)" : "%3";
fmt += rOp && ( rOp->precedence() < precedence() || !rOp->rightAssociative() ) ? "(%3)" : "%3";
return fmt.arg( mOpLeft->dump() ).arg( BinaryOperatorText[mOp] ).arg( mOpRight->dump() );
}

View File

@ -513,6 +513,8 @@ class CORE_EXPORT QgsExpression
virtual void accept( Visitor& v ) const override { v.visit( *this ); }
int precedence() const;
bool leftAssociative() const;
bool rightAssociative() const;
protected:
bool compare( double diff );

View File

@ -523,6 +523,9 @@ class TestQgsExpression: public QObject
QgsExpression e2( e1.dump() );
QCOMPARE( e2.evaluate().toInt(), 21 );
QgsExpression e3( "(2^3)^2" );
QCOMPARE( QgsExpression( e3.dump() ).evaluate().toInt(), 64 );
}
void eval_columns()