private String compileFactor(Node factor) throws CompilationErrorException {
        StringBuilder builder = new StringBuilder();

        if (factor.getNodeType() != NodeType.FACTOR) {
            builder.append(compilePower(factor));
        } else {
            builder.append(compilePower(factor.getChild(0)));
            ValueType firstType = typeOnStack;

            String operation;

            switch (factor.getValueToken().getType()) {
                case POWER:
                    operation = "POWER";
                    break;
                default:
                    throw new CompilationErrorException("Unknown operation with two parameters: " + factor.getValueToken().getType());
            }

            builder.append(compileFactor(factor.getChild(1)));
            ValueType secondType = typeOnStack;

            if (firstType == ValueType.I && secondType == ValueType.I) {
                builder.append(CodeBuilder.CODE_INDENT)
                        .append("i").append(operation).append("\n");
                typeOnStack = ValueType.I;
            } else {
                if (firstType == ValueType.D) {
                    // cast second argument ( stack top ) to double
                    builder.append(CodeBuilder.CODE_INDENT).append("i2d                   ; cast integer on stack to double\n");
                    popped(ValueType.I);
                    pushed(ValueType.D);
                } else if (secondType == ValueType.D) {
                    // cast first argument ( stack second ) to double
                    int index = getMinVariableIndex(ValueType.D);
                    builder.append(CodeBuilder.storeStackToVariable(ValueType.D, index, "temp"));
                    popped(ValueType.I);
                    builder.append(CodeBuilder.cast(ValueType.I, ValueType.D));
                    popped(ValueType.I);
                    pushed(ValueType.D);
                    builder.append(CodeBuilder.loadVariableToStack(ValueType.D, index, "temp"));
                    pushed(ValueType.D);
                }

                builder.append(CodeBuilder.CODE_INDENT)
                        .append("d").append(operation).append("\n");
                typeOnStack = ValueType.D;

                popped(typeOnStack);
            }
        }

        return builder.toString();
    }