private ExpressionNode parseBinaryExpression(int precedence, ExpressionNode leftExpression) {
            for (;;) {
                var prec = 0;
                var doParseType = false;
                var op = BinaryOperator.Add;
                var restorePoint = this.createRestorePoint();
                switch (lexicalUnit) {
                case Multiply:
                    prec = 1;
                    op = BinaryOperator.Multiply;
                    break;

                case Divide:
                    prec = 1;
                    op = BinaryOperator.Divide;
                    break;

                case Percent:
                    prec = 1;
                    op = BinaryOperator.Modulo;
                    break;

                case Plus:
                    prec = 2;
                    op = BinaryOperator.Add;
                    break;

                case Minus:
                    prec = 2;
                    op = BinaryOperator.Subtract;
                    break;

                case LeftShift:
                    prec = 3;
                    op = BinaryOperator.LeftShift;
                    break;

                case GreaterThan:
                    switch (scanner.nextLexicalUnit()) {
                    case GreaterThan:
                        restorePoint = createRestorePoint();
                        switch (scanner.nextLexicalUnit()) {
                        case GreaterThan:
                            prec = 3;
                            op = BinaryOperator.UnsignedRightShift;
                            break;
                        default:
                            this.restore(restorePoint);
                            prec = 3;
                            op = BinaryOperator.RightShift;
                            break;
                        case GreaterThanOrEqual:
                            this.restore(restorePoint);
                            return leftExpression;
                        }
                        break;
                    default:
                        this.restore(restorePoint);
                        prec = 4;
                        op = BinaryOperator.GreaterThan;
                        break;
                    case GreaterThanOrEqual:
                        this.restore(restorePoint);
                        return leftExpression;
                    }
                    break;

                case LessThan:
                    prec = 4;
                    op = BinaryOperator.LessThan;
                    break;

                case LessThanOrEqual:
                    prec = 4;
                    op = BinaryOperator.LessThanOrEqual;
                    break;

                case GreaterThanOrEqual:
                    prec = 4;
                    op = BinaryOperator.GreaterThanOrEqual;
                    break;

                case Keyword:
                    switch (scanner.Keyword) {
                    case As:
                        prec = 4;
                        doParseType = true;
                        op = BinaryOperator.As;
                        break;

                    case Instanceof:
                        prec = 4;
                        doParseType = true;
                        op = BinaryOperator.Instanceof;
                        break;

                    default:
                        return leftExpression;
                    }
                    break;

                case Equal:
                    prec = 5;
                    op = BinaryOperator.Equal;
                    break;

                case NotEqual:
                    prec = 5;
                    op = BinaryOperator.NotEqual;
                    break;

                case LogicalAnd:
                    prec = 6;
                    op = BinaryOperator.LogicalAnd;
                    break;

                case Xor:
                    prec = 7;
                    op = BinaryOperator.Xor;
                    break;

                case LogicalOr:
                    prec = 8;
                    op = BinaryOperator.LogicalOr;
                    break;

                case And:
                    prec = 9;
                    op = BinaryOperator.And;
                    break;

                case Or:
                    prec = 10;
                    op = BinaryOperator.Or;
                    break;

                case NullCoalescing:
                    prec = 11;
                    op = BinaryOperator.NullCoalescing;
                    break;

                default:
                    return leftExpression;
                }
                if (prec > precedence) {
                    if (op == BinaryOperator.RightShift) {
                        this.restore(restorePoint);
                    }
                    return leftExpression;
                }
                nextLexicalUnit(true);
                var binary = new BinaryExpressionNode { Operator = op, LeftOperand = leftExpression };
                copyScannerState(leftExpression, binary);
                if (doParseType) {
                    var type = new TypeExpressionNode { TypeReference = parseType(true) };
                    copyScannerState(type.TypeReference, type);
                    type.EndPosition = type.TypeReference.EndPosition;
                    binary.RightOperand = type;
                } else {
                    binary.RightOperand = parseBinaryExpression(prec - 1, parseUnaryExpression());
                }
                binary.EndPosition = binary.RightOperand.EndPosition;
                leftExpression = binary;
            }
        }