diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 9ab40ce6f7502b58bcc034286e736ae27705ed43..cc7f0da2112fdaeecafffd2b95ea5b9fe0e0aab3 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -59,6 +59,7 @@
 #endif
 
 #define CPLUSPLUS_NO_DEBUG_RULE
+#define MAX_EXPRESSION_DEPTH 100
 
 using namespace CPlusPlus;
 
@@ -85,6 +86,73 @@ public:
 
 int DebugRule::depth = 0;
 
+inline int precedence(int tokenKind, bool templateArguments)
+{
+    if (templateArguments && tokenKind == T_GREATER)
+        return -1;
+
+    switch (tokenKind) {
+    case T_PIPE_PIPE:       return 0;
+    case T_AMPER_AMPER:     return 1;
+    case T_PIPE:            return 2;
+    case T_CARET:           return 3;
+    case T_AMPER:           return 4;
+    case T_EQUAL_EQUAL:
+    case T_EXCLAIM_EQUAL:   return 5;
+    case T_GREATER:
+    case T_LESS:
+    case T_LESS_EQUAL:
+    case T_GREATER_EQUAL:   return 6;
+    case T_LESS_LESS:
+    case T_GREATER_GREATER: return 7;
+    case T_PLUS:
+    case T_MINUS:           return 8;
+    case T_STAR:
+    case T_SLASH:
+    case T_PERCENT:         return 9;
+    case T_ARROW_STAR:
+    case T_DOT_STAR:        return 10;
+
+    default:
+        return -1;
+    }
+}
+
+inline bool isBinaryOperator(int tokenKind)
+{
+    switch (tokenKind) {
+    case T_PIPE_PIPE:
+    case T_AMPER_AMPER:
+    case T_PIPE:
+    case T_CARET:
+    case T_AMPER:
+    case T_EQUAL_EQUAL:
+    case T_EXCLAIM_EQUAL:
+    case T_GREATER:
+    case T_LESS:
+    case T_LESS_EQUAL:
+    case T_GREATER_EQUAL:
+    case T_LESS_LESS:
+    case T_GREATER_GREATER:
+    case T_PLUS:
+    case T_MINUS:
+    case T_STAR:
+    case T_SLASH:
+    case T_PERCENT:
+    case T_ARROW_STAR:
+    case T_DOT_STAR:
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+inline bool isRightAssoc(int /*tokenKind*/)
+{
+    return false;
+}
+
 } // end of anonymous namespace
 
 #ifndef CPLUSPLUS_NO_DEBUG_RULE
@@ -93,6 +161,14 @@ int DebugRule::depth = 0;
 #  define DEBUG_THIS_RULE() do {} while (0)
 #endif
 
+#define PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, minPrecedence) { \
+    if (!parseCastExpression(node)) \
+        return false; \
+    \
+    parseExpressionWithOperatorPrecedence(node, minPrecedence); \
+    return true; \
+}
+
 class Parser::Rewind
 {
     Parser *_parser;
@@ -127,7 +203,7 @@ Parser::Parser(TranslationUnit *unit)
       _objCEnabled(false),
       _inFunctionBody(false),
       _inObjCImplementationContext(false),
-      depth(0)
+      _expressionDepth(0)
 { }
 
 Parser::~Parser()
@@ -4145,280 +4221,57 @@ bool Parser::parseCastExpression(ExpressionAST *&node)
 
 bool Parser::parsePmExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseCastExpression(node))
-        return false;
-
-    while (LA() == T_ARROW_STAR || LA() == T_DOT_STAR) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseCastExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_ARROW_STAR, _templateArguments))
 }
 
 bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parsePmExpression(node))
-        return false;
-
-    while (LA() == T_STAR || LA() == T_SLASH || LA() == T_PERCENT) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parsePmExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_STAR, _templateArguments))
 }
 
 bool Parser::parseAdditiveExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseMultiplicativeExpression(node))
-        return false;
-
-    while (LA() == T_PLUS || LA() == T_MINUS) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseMultiplicativeExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_PLUS, _templateArguments))
 }
 
 bool Parser::parseShiftExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseAdditiveExpression(node))
-        return false;
-
-    while (LA() == T_LESS_LESS || LA() == T_GREATER_GREATER) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseAdditiveExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_LESS_LESS, _templateArguments))
 }
 
 bool Parser::parseRelationalExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseShiftExpression(node))
-        return false;
-
-    while (LA() == T_LESS || (LA() == T_GREATER && ! _templateArguments) ||
-           LA() == T_LESS_EQUAL || LA() == T_GREATER_EQUAL) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseShiftExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_LESS, _templateArguments))
 }
 
 bool Parser::parseEqualityExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseRelationalExpression(node))
-        return false;
-
-    while (LA() == T_EQUAL_EQUAL || LA() == T_EXCLAIM_EQUAL) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseRelationalExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_EQUAL_EQUAL, _templateArguments))
 }
 
 bool Parser::parseAndExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseEqualityExpression(node))
-        return false;
-
-    while (LA() == T_AMPER) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseEqualityExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_AMPER, _templateArguments))
 }
 
 bool Parser::parseExclusiveOrExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseAndExpression(node))
-        return false;
-
-    while (LA() == T_CARET) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseAndExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_CARET, _templateArguments))
 }
 
 bool Parser::parseInclusiveOrExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseExclusiveOrExpression(node))
-        return false;
-
-    while (LA() == T_PIPE) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseExclusiveOrExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_PIPE, _templateArguments))
 }
 
 bool Parser::parseLogicalAndExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseInclusiveOrExpression(node))
-        return false;
-
-    while (LA() == T_AMPER_AMPER) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseInclusiveOrExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_AMPER_AMPER, _templateArguments))
 }
 
 bool Parser::parseLogicalOrExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseLogicalAndExpression(node))
-        return false;
-
-    while (LA() == T_PIPE_PIPE) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseLogicalAndExpression(rightExpr)) {
-            _translationUnit->error(op, "expected expression after token `%s'",
-                                    _translationUnit->spell(op));
-            return false;
-        }
-
-        BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
-        ast->binary_op_token = op;
-        ast->left_expression = node;
-        ast->right_expression = rightExpr;
-        node = ast;
-    }
-
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, precedence(T_PIPE_PIPE, _templateArguments))
 }
 
 bool Parser::parseConditionalExpression(ExpressionAST *&node)
@@ -4515,13 +4368,40 @@ bool Parser::parseConstantExpression(ExpressionAST *&node)
 bool Parser::parseExpression(ExpressionAST *&node)
 {
     DEBUG_THIS_RULE();
-    if (depth > 100)
+
+    if (_expressionDepth > MAX_EXPRESSION_DEPTH)
         return false;
 
-    ++depth;
-    bool result = parseCommaExpression(node);
-    --depth;
-    return result;
+    ++_expressionDepth;
+    bool success = parseCommaExpression(node);
+    --_expressionDepth;
+    return success;
+}
+
+void Parser::parseExpressionWithOperatorPrecedence(ExpressionAST *&lhs, int minPrecedence)
+{
+    DEBUG_THIS_RULE();
+
+    while (precedence(tok().kind(), _templateArguments) >= minPrecedence) {
+        const int operPrecedence = precedence(tok().kind(), _templateArguments);
+        const int oper = consumeToken();
+        ExpressionAST *rhs = 0;
+        if (!parseCastExpression(rhs))
+            return;
+
+        for (int tokenKindAhead = tok().kind(), precedenceAhead = precedence(tokenKindAhead, _templateArguments);
+                precedenceAhead > operPrecedence && isBinaryOperator(tokenKindAhead)
+                    || precedenceAhead == operPrecedence && isRightAssoc(tokenKindAhead);
+                tokenKindAhead = tok().kind(), precedenceAhead = precedence(tokenKindAhead, _templateArguments)) {
+            parseExpressionWithOperatorPrecedence(rhs, precedenceAhead);
+        }
+
+        BinaryExpressionAST *expr = new (_pool) BinaryExpressionAST;
+        expr->left_expression = lhs;
+        expr->binary_op_token = oper;
+        expr->right_expression = rhs;
+        lhs = expr;
+    }
 }
 
 bool Parser::parseCommaExpression(ExpressionAST *&node)
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index 7d72c7ef399663867167fb449f533820f0a98aa4..0c48ab9c545ab91706670180d223f517e223e096 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -214,6 +214,8 @@ public:
     bool parseUsingDirective(DeclarationAST *&node);
     bool parseWhileStatement(StatementAST *&node);
 
+    void parseExpressionWithOperatorPrecedence(ExpressionAST *&lhs, int minPrecedence);
+
     // Qt MOC run
     bool parseQtMethod(ExpressionAST *&node);
 
@@ -313,8 +315,7 @@ private:
     bool _objCEnabled: 1;
     bool _inFunctionBody: 1;
     bool _inObjCImplementationContext: 1;
-
-    int depth;
+    int _expressionDepth;
 
     std::map<unsigned, TemplateArgumentListEntry> _templateArgumentList;
 
diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp
index 6e160201600108f9de8bcd4c187ab93ee9b2444f..f33d793f3767ef74e18aa78d8f19d5a6ed8ca6da 100644
--- a/tests/auto/cplusplus/ast/tst_ast.cpp
+++ b/tests/auto/cplusplus/ast/tst_ast.cpp
@@ -185,11 +185,56 @@ void tst_AST::new_expression_2()
 void tst_AST::condition_1()
 {
     QSharedPointer<TranslationUnit> unit(parseExpression("\n"
-"(x < 0 && y > (int) a)"
+                                                         "(x < 0 && y > (int) a)"
     ));
 
     AST *ast = unit->ast();
     QVERIFY(ast != 0);
+    NestedExpressionAST *nestedExpr = ast->asNestedExpression();
+    QVERIFY(nestedExpr);
+    QVERIFY(nestedExpr->expression);
+    BinaryExpressionAST *andExpr = nestedExpr->expression->asBinaryExpression();
+    QVERIFY(andExpr);
+    QCOMPARE(unit->tokenKind(andExpr->binary_op_token), (int) T_AMPER_AMPER);
+    QVERIFY(andExpr->left_expression);
+    QVERIFY(andExpr->right_expression);
+
+    BinaryExpressionAST *ltExpr = andExpr->left_expression->asBinaryExpression();
+    QVERIFY(ltExpr);
+    QCOMPARE(unit->tokenKind(ltExpr->binary_op_token), (int) T_LESS);
+    QVERIFY(ltExpr->left_expression);
+    QVERIFY(ltExpr->right_expression);
+
+    SimpleNameAST *x = ltExpr->left_expression->asSimpleName();
+    QVERIFY(x);
+    QCOMPARE(unit->spell(x->identifier_token), "x");
+
+    NumericLiteralAST *zero = ltExpr->right_expression->asNumericLiteral();
+    QVERIFY(zero);
+    QCOMPARE(unit->spell(zero->literal_token), "0");
+
+    BinaryExpressionAST *gtExpr = andExpr->right_expression->asBinaryExpression();
+    QVERIFY(gtExpr);
+    QCOMPARE(unit->tokenKind(gtExpr->binary_op_token), (int) T_GREATER);
+    QVERIFY(gtExpr->left_expression);
+    QVERIFY(gtExpr->right_expression);
+
+    SimpleNameAST *y = gtExpr->left_expression->asSimpleName();
+    QVERIFY(y);
+    QCOMPARE(unit->spell(y->identifier_token), "y");
+
+    CastExpressionAST *cast = gtExpr->right_expression->asCastExpression();
+    QVERIFY(cast);
+    QVERIFY(cast->type_id);
+    QVERIFY(cast->expression);
+
+    TypeIdAST *intType = cast->type_id->asTypeId();
+    QVERIFY(intType);
+    // ### here we could check if the type is an actual int
+
+    SimpleNameAST *a = cast->expression->asSimpleName();
+    QVERIFY(a);
+    QCOMPARE(unit->spell(a->identifier_token), "a");
 }
 
 void tst_AST::init_1()