Skip to content
Permalink
Browse files

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

…binary operators

complete test for left associativity
  • Loading branch information
3nids authored and m-kuhn committed Dec 11, 2014
1 parent 0bf1135 commit a518e9f639eb2e40c17b18b7b60ebac0973855fb
Showing with 81 additions and 2 deletions.
  1. +2 −0 python/core/qgsexpression.sip
  2. +74 −2 src/core/qgsexpression.cpp
  3. +2 −0 src/core/qgsexpression.h
  4. +3 −0 tests/src/core/testqgsexpression.cpp
@@ -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
@@ -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() );
}
@@ -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 );
@@ -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()

0 comments on commit a518e9f

Please sign in to comment.
You can’t perform that action at this time.