diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index dece2dbe53b8af09090d44054e01aba9c07a99b5..6c3290f4f1895f6cbdf6f4379559a4f30db3bf08 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -107,8 +107,7 @@ inline bool lookAtAssignmentOperator(int tokenKind)
     } // switch
 }
 
-namespace Prec { // operator-precedence
-
+namespace Prec {
 enum {
     Unknown         = 0,
     Comma           = 1,
@@ -126,46 +125,53 @@ enum {
     Multiplicative  = 13,
     PointerToMember = 14
 };
+} // end of namespace Precedece
 
 inline int precedence(int tokenKind, bool templateArguments)
 {
+    // ### this will/might need some tuning for C++0x
+    // (see: [temp.names]p3)
     if (templateArguments && tokenKind == T_GREATER)
         return -1;
 
     if (lookAtAssignmentOperator(tokenKind))
-        return Assignment;
+        return Prec::Assignment;
 
     switch (tokenKind) {
-    case T_COMMA:           return Comma;
-    case T_QUESTION:        return Conditional;
-    case T_PIPE_PIPE:       return LogicalOr;
-    case T_AMPER_AMPER:     return LogicalAnd;
-    case T_PIPE:            return InclusiveOr;
-    case T_CARET:           return ExclusiveOr;
-    case T_AMPER:           return And;
+    case T_COMMA:           return Prec::Comma;
+    case T_QUESTION:        return Prec::Conditional;
+    case T_PIPE_PIPE:       return Prec::LogicalOr;
+    case T_AMPER_AMPER:     return Prec::LogicalAnd;
+    case T_PIPE:            return Prec::InclusiveOr;
+    case T_CARET:           return Prec::ExclusiveOr;
+    case T_AMPER:           return Prec::And;
     case T_EQUAL_EQUAL:
-    case T_EXCLAIM_EQUAL:   return Equality;
+    case T_EXCLAIM_EQUAL:   return Prec::Equality;
     case T_GREATER:
     case T_LESS:
     case T_LESS_EQUAL:
-    case T_GREATER_EQUAL:   return Relational;
+    case T_GREATER_EQUAL:   return Prec::Relational;
     case T_LESS_LESS:
-    case T_GREATER_GREATER: return ExclusiveOr;
+    case T_GREATER_GREATER: return Prec::ExclusiveOr;
     case T_PLUS:
-    case T_MINUS:           return Additive;
+    case T_MINUS:           return Prec::Additive;
     case T_STAR:
     case T_SLASH:
-    case T_PERCENT:         return Multiplicative;
+    case T_PERCENT:         return Prec::Multiplicative;
     case T_ARROW_STAR:
-    case T_DOT_STAR:        return PointerToMember;
-    default:                return Unknown;
+    case T_DOT_STAR:        return Prec::PointerToMember;
+    default:                return Prec::Unknown;
     }
 }
 
-} // end of namespace Precedece
-
 inline bool isBinaryOperator(int tokenKind)
-{ return Prec::precedence(tokenKind, false) != Prec::Unknown; }
+{ return precedence(tokenKind, false) != Prec::Unknown; }
+
+inline bool isRightAssociative(int tokenKind)
+{
+    const int prec = precedence(tokenKind, false);
+    return prec == Prec::Conditional || prec == Prec::Assignment;
+}
 
 } // end of anonymous namespace
 
@@ -4250,76 +4256,62 @@ bool Parser::parseCastExpression(ExpressionAST *&node)
 
 bool Parser::parsePmExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_ARROW_STAR, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::PointerToMember)
 }
 
 bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_STAR, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Multiplicative)
 }
 
 bool Parser::parseAdditiveExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_PLUS, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Additive)
 }
 
 bool Parser::parseShiftExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_LESS_LESS, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Shift)
 }
 
 bool Parser::parseRelationalExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_LESS, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Relational)
 }
 
 bool Parser::parseEqualityExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_EQUAL_EQUAL, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Equality)
 }
 
 bool Parser::parseAndExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_AMPER, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::And)
 }
 
 bool Parser::parseExclusiveOrExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_CARET, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::ExclusiveOr)
 }
 
 bool Parser::parseInclusiveOrExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_PIPE, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::InclusiveOr)
 }
 
 bool Parser::parseLogicalAndExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_AMPER_AMPER, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::LogicalAnd)
 }
 
 bool Parser::parseLogicalOrExpression(ExpressionAST *&node)
 {
-    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::precedence(T_PIPE_PIPE, _templateArguments))
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::LogicalOr)
 }
 
 bool Parser::parseConditionalExpression(ExpressionAST *&node)
 {
-    DEBUG_THIS_RULE();
-    if (! parseLogicalOrExpression(node))
-        return false;
-
-    if (LA() != T_QUESTION)
-        return true;
-
-    ConditionalExpressionAST *ast = new (_pool) ConditionalExpressionAST;
-    ast->condition = node;
-    ast->question_token = consumeToken();
-    parseAssignmentExpression(ast->left_expression);
-    match(T_COLON, &ast->colon_token);
-    parseAssignmentExpression(ast->right_expression);
-    node = ast;
-    return true;
+    PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Conditional)
 }
 
 bool Parser::parseAssignmentExpression(ExpressionAST *&node)
@@ -4327,27 +4319,8 @@ bool Parser::parseAssignmentExpression(ExpressionAST *&node)
     DEBUG_THIS_RULE();
     if (LA() == T_THROW)
         return parseThrowExpression(node);
-    else if (! parseConditionalExpression(node))
-        return false;
-
-    if (lookAtAssignmentOperator(LA())) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseAssignmentExpression(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;
+    else
+        PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Assignment)
 }
 
 bool Parser::parseQtMethod(ExpressionAST *&node)
@@ -4390,47 +4363,61 @@ void Parser::parseExpressionWithOperatorPrecedence(ExpressionAST *&lhs, int minP
 {
     DEBUG_THIS_RULE();
 
-    while (Prec::precedence(tok().kind(), _templateArguments) >= minPrecedence) {
-        const int operPrecedence = Prec::precedence(tok().kind(), _templateArguments);
+    while (precedence(tok().kind(), _templateArguments) >= minPrecedence) {
+        const int operPrecedence = precedence(tok().kind(), _templateArguments);
         const int oper = consumeToken();
+
+        ConditionalExpressionAST *condExpr = 0;
+        if (operPrecedence == Prec::Conditional) {
+            condExpr = new (_pool) ConditionalExpressionAST;
+            condExpr->question_token = oper;
+            if (oper == T_COLON) {
+                // GNU extension:
+                //   logical-or-expression '?' ':' conditional-expression
+                condExpr->left_expression = 0;
+            } else {
+                parseExpression(condExpr->left_expression);
+            }
+            match(T_COLON, &condExpr->colon_token);
+        }
+
         ExpressionAST *rhs = 0;
-        if (!parseCastExpression(rhs))
-            return;
+        const bool isCPlusPlus = true;
+        if (operPrecedence <= Prec::Conditional && isCPlusPlus) {
+            // in C++ you can put a throw in the right-most expression of a conditional expression,
+            // or an assignment, so some special handling:
+            if (!parseAssignmentExpression(rhs))
+                return;
+        } else {
+            // for C & all other expressions:
+            if (!parseCastExpression(rhs))
+                return;
+        }
 
-        for (int tokenKindAhead = tok().kind(), precedenceAhead = Prec::precedence(tokenKindAhead, _templateArguments);
-                precedenceAhead > operPrecedence && isBinaryOperator(tokenKindAhead);
-                tokenKindAhead = tok().kind(), precedenceAhead = Prec::precedence(tokenKindAhead, _templateArguments)) {
+        for (int tokenKindAhead = tok().kind(), precedenceAhead = precedence(tokenKindAhead, _templateArguments);
+                precedenceAhead > operPrecedence && isBinaryOperator(tokenKindAhead)
+                        || precedenceAhead == operPrecedence && isRightAssociative(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;
+        if (condExpr) { // we were parsing a ternairy conditional expression
+            condExpr->condition = lhs;
+            condExpr->right_expression = rhs;
+            lhs = condExpr;
+        } else {
+            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)
 {
-    DEBUG_THIS_RULE();
-    if (! parseAssignmentExpression(node))
-        return false;
-
-    while (LA() == T_COMMA) {
-        unsigned op = consumeToken();
-
-        ExpressionAST *rightExpr = 0;
-        if (! parseAssignmentExpression(rightExpr))
-            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, Prec::Comma)
 }
 
 bool Parser::parseThrowExpression(ExpressionAST *&node)
diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp
index bee94326cfa776aac05c7061039f2a5293dd4660..c9c8b73f46370b0c31db5d9301c5085112c9a89e 100644
--- a/tests/auto/cplusplus/ast/tst_ast.cpp
+++ b/tests/auto/cplusplus/ast/tst_ast.cpp
@@ -50,6 +50,7 @@ private slots:
     void new_expression_2();
     void condition_1();
     void init_1();
+    void conditional_1();
 
     // statements
     void if_statement_1();
@@ -248,6 +249,98 @@ void tst_AST::init_1()
     QVERIFY(ast != 0);
 }
 
+void tst_AST::conditional_1()
+{
+    QSharedPointer<TranslationUnit> unit(parseExpression("\n"
+                                                         "(x < 0 && y > (int) a) ? x == 1 : y = 1"
+    ));
+
+    AST *ast = unit->ast();
+    QVERIFY(ast != 0);
+
+    ConditionalExpressionAST *conditional = ast->asConditionalExpression();
+    QVERIFY(conditional);
+    QVERIFY(conditional->condition);
+    QVERIFY(conditional->left_expression);
+    QVERIFY(conditional->right_expression);
+
+    NestedExpressionAST *nestedExpr = conditional->condition->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);
+    QVERIFY(! (intType->declarator));
+    QVERIFY(intType->type_specifier_list);
+    QVERIFY(! (intType->type_specifier_list->next));
+    QVERIFY(intType->type_specifier_list->value);
+    SimpleSpecifierAST *intSpec = intType->type_specifier_list->value->asSimpleSpecifier();
+    QVERIFY(intSpec);
+    QCOMPARE(unit->spell(intSpec->specifier_token), "int");
+
+    SimpleNameAST *a = cast->expression->asSimpleName();
+    QVERIFY(a);
+    QCOMPARE(unit->spell(a->identifier_token), "a");
+
+    BinaryExpressionAST *equals = conditional->left_expression->asBinaryExpression();
+    QVERIFY(equals);
+    QCOMPARE(unit->tokenKind(equals->binary_op_token), (int) T_EQUAL_EQUAL);
+
+    x = equals->left_expression->asSimpleName();
+    QVERIFY(x);
+    QCOMPARE(unit->spell(x->identifier_token), "x");
+
+    NumericLiteralAST *one = equals->right_expression->asNumericLiteral();
+    QVERIFY(one);
+    QCOMPARE(unit->spell(one->literal_token), "1");
+
+    BinaryExpressionAST *assignment = conditional->right_expression->asBinaryExpression();
+    QVERIFY(assignment);
+    QCOMPARE(unit->tokenKind(assignment->binary_op_token), (int) T_EQUAL);
+
+    y = assignment->left_expression->asSimpleName();
+    QVERIFY(y);
+    QCOMPARE(unit->spell(y->identifier_token), "y");
+
+    one = assignment->right_expression->asNumericLiteral();
+    QVERIFY(one);
+    QCOMPARE(unit->spell(one->literal_token), "1");
+}
+
 void tst_AST::function_call_1()
 {
     QSharedPointer<TranslationUnit> unit(parseStatement("retranslateUi(blah);"));