@Override
  protected final IASTNode doResolveAmbiguity(ASTVisitor visitor) {
    final IASTAmbiguityParent owner = (IASTAmbiguityParent) getParent();
    IASTNode nodeToReplace = this;

    // handle nested ambiguities first
    owner.replace(nodeToReplace, fCastExpression);
    nodeToReplace = fCastExpression;
    fCastExpression.getTypeId().accept(visitor);

    owner.replace(nodeToReplace, fBinaryExpression);
    nodeToReplace = fBinaryExpression;
    fBinaryExpression.accept(visitor);

    // find nested names
    final NameCollector nameCollector = new NameCollector();
    fCastExpression.getTypeId().accept(nameCollector);
    final IASTName[] names = nameCollector.getNames();

    // resolve names
    boolean hasIssue = false;
    for (IASTName name : names) {
      try {
        IBinding b = name.resolveBinding();
        if (b instanceof IProblemBinding) {
          hasIssue = true;
          break;
        }
      } catch (Exception t) {
        hasIssue = true;
        break;
      }
    }
    if (hasIssue) {
      return nodeToReplace;
    }

    final IASTExpression left = fBinaryExpression.getOperand1();
    final IASTExpression right = fBinaryExpression.getOperand2();
    left.setParent(null);
    right.setParent(null);
    IASTUnaryExpression primaryInParenthesis = findTrailingBracketedPrimaryExpression(left);
    IASTExpression leadingCastExpression = findLeadingCastExpression(right);
    IASTExpression castedUnary = fCastExpression.getOperand();
    if (primaryInParenthesis != null
        && leadingCastExpression != null
        && castedUnary instanceof IASTUnaryExpression) {
      IASTExpression lp = (IASTExpression) primaryInParenthesis.getParent();
      IASTBinaryExpression rp = (IASTBinaryExpression) leadingCastExpression.getParent();
      ((IASTUnaryExpression) castedUnary).setOperand(leadingCastExpression);
      setEnd(castedUnary, leadingCastExpression);
      setRange(fCastExpression, primaryInParenthesis, leadingCastExpression);
      IASTExpression root = joinExpressions(lp, fCastExpression, rp);
      if (root != null) {
        owner.replace(nodeToReplace, root);
        return root;
      }
    }
    return nodeToReplace;
  }
 /**
  * @param l unary, cast or binary expression to the left, all parents are unary, cast or binary
  *     expressions.
  * @param middle initially a cast-expression, always suitable to put into l or r
  * @param r a binary expression to the right, all parents are binary expressions.
  */
 private IASTExpression joinExpressions(
     IASTExpression l, IASTExpression middle, IASTBinaryExpression r) {
   while (true) {
     if (l == null) {
       if (r == null) {
         return middle;
       }
       r.setOperand1(middle);
       setStart(r, middle);
       middle = r;
       r = (IASTBinaryExpression) r.getParent();
     } else if (l instanceof IASTCastExpression) {
       // cast binds stronger than binary operator
       ((IASTCastExpression) l).setOperand(middle);
       setEnd(l, middle);
       middle = l; // middle becomes cast-expr, can be put into r (a binary-expr)
       l = (IASTExpression) l.getParent();
     } else if (l instanceof IASTUnaryExpression) { //
       // unary operator binds stronger than binary operator
       ((IASTUnaryExpression) l).setOperand(middle);
       setEnd(l, middle);
       middle = l; // middle becomes unary-expr, can be put into r (a binary-expr)
       l = (IASTExpression) l.getParent();
     } else {
       if (r == null || getPrecendence((IASTBinaryExpression) l) >= getPrecendence(r)) {
         ((IASTBinaryExpression) l).setOperand2(middle);
         setEnd(l, middle);
         middle =
             l; // middle becomes binary, can be put into r because precedence is greater or equal.
         l = (IASTExpression) l.getParent();
       } else {
         r.setOperand1(middle);
         setStart(r, middle);
         middle = r; // middle becomes binary, can be put into r because precedence is greater.
         r = (IASTBinaryExpression) r.getParent();
       }
     }
   }
 }