This is a pretty straightforward answer. It just translates each "command" to the vim keystroke equivalent of that command. Let's take it line by line.

:no s :%s/\M[

This saves a ton of bytes. Vim has a builtin "command line" where you can create mappings, change settings, save files, etc. Here we are creating a mapping. :no is short for :nnoremap which means "When we are in normal mode, substitute this left hand side for this right hand side." Since we are calling :%s/five different times, this saves a lot. The \M is a nice trick. It means that the following search will be "Very No Magic", which means that the regex [B] will match the literal text [B] rather than a range containing just a B in it. Since the majority of the substitute commands have a brackets in them, we fill in the first one.

Then, we call five substitute commands. It's worth noting why I called <C-v> so many times. Characters like <esc>, <C-v>, <C-r>, etc. are unprintable characters, and must be typed into the command line with a <C-v>.

[B]: backspace. This one is pretty easy. Simply substitute each [B] with Ctrl-h, which is equivalent to backspace in vim.

[C]: copy all of what has already been written. This is translated to <esc>0y$A. This means:

<esc> " Escape to normal mode
0 " Move to the beginning of this line
y$ " Yank to the end of the line
A " Re enter insert mode at the end of this line.

We could almost simply do Y in place of 0y$ which means "yank the whole line", but this also grabs a newline that we don't want.

[D]: delete all of what has been written. This is <esc>"_S. As before, <esc> exits insert mode so we can run commands. There are some things that are more convenient here. So we do

S " Delete this whole line and enter insert mode again
"_ " Send it to 'the black hole register'. This is just so that we don't overwrite the main register.

[P]: paste what has been copied. This one is also very straightforward. It is just <C-r>" which means Insert the contents of register '"'. " happens to be the main register that 'y' yanks to.

Now that we have translated all of the commands, we must join all the lines together by removing all of the newline characters. Thanks to our mapping, this is just

s<bs>\n

The <bs> is a backspace, (ASCII 0x08) and we need it because of the [ we filled in.

By now, we have translated the input into vim code, and we just need to run it. So we:

S " Delete this whole line and enter insert mode
<C-r>" " Insert the keystrokes of register '"' as if they were typed by the user

\$\begingroup\$@Neil In general, you can find a key for a specific mode at :h mode_keystroke. In this case, it would be :h i_ctrl-r\$\endgroup\$
– DJMcMayhem♦Oct 9 '16 at 23:34

\$\begingroup\$@Loovjo Oh sorry, I forgot to mention. Input is expected to be on multiple lines so that I don't have to worry about commas, or the /g flag. I'll add those details in.\$\endgroup\$
– DJMcMayhem♦Oct 10 '16 at 5:25

Explanation

q~ Read an evaluate input list.
{ }% Map over each string in it:
_ Duplicate the string, say S.
[`';"];""L~""]:L~"] Replace it the following list:
[repr(S) '; "];" "L~" "]:L~"]
\ Bring S on top of the stack.
1> Chop off the first char.
3b Base-3 conversion.
= Modular index into the list.
s~ Concatenate and run as CJam code.

The “hash function” 1>3b maps

single-character strings to 0 (= 0 mod 5),

[B] to 291 (= 1 mod 5),

[D] to 297 (= 2 mod 5),

[P] to 333 (= 3 mod 5),

[C] to 294 (= 4 mod 5).

This value (mod 5) is used as an index into a list of CJam code snippets:

For single-character strings, say h, the snippet "h" is returned, which pushes a single-character string to the stack.

For [B], the snippet ; is returned, which pops an element.

For [D], the snippet ]; is returned, which clears the stack.

For [P], the snippet L~ is returned, which appends variable L onto the stack.

For [C], the snippet ]:L~ is returned, which stores the current stack in the variable L.

These snippets are concatenated and executed; the final stack is printed implicitly by CJam. L is initially the empty list, so the copy buffer is initially “empty”.

\$\begingroup\$Ah - yes I missed this edge case, there is a copy before deleting the entire string and the code I wrote ignores it. I will look at it a little later, thanks for notifying me.\$\endgroup\$
– Jonathan AllanOct 10 '16 at 7:48

\$\begingroup\$OK I fixed that up and it actually saves bytes too!\$\endgroup\$
– Jonathan AllanOct 10 '16 at 8:21

Python 120 119 116 bytes

Each recursive call updates the return text, r and, in the case of a [C], the clipboard, c until s is empty.

The new values of r and c are found by indexing into a dictionary, {...}, and passed with unpacking, *. For the passive keystrokes s[0][1:2]will return an empty string and the key '' will be used instead.

\$\begingroup\$@nimi That's clever, thanks! As for the anonymous function I somehow had in mind that anonymous functions are only acceptable when they are the only statement and there are no other helper functions. However searching Meta turned up nothing like that, so I guess it's ok.\$\endgroup\$
– LaikoniOct 10 '16 at 18:02

\$\begingroup\$$s=$argv[++$i] instead of null!==$s=$argv[++$i] if you use PHP >7 you could write $s=$argv[++$i]??0 to skip the notice\$\endgroup\$
– Jörg HülsermannOct 10 '16 at 15:12

1

\$\begingroup\$It's not there to skip the notice but to allow you to enter '0' seeing as how '0' is false. There are so many other notices that skipping that one in particular seems like a waste of time.\$\endgroup\$
– user59178Oct 10 '16 at 15:27

Actually, 56 bytes

''j"'[B]"'XaÆ"'[C]""k;╗i"aÆ"'[P]""╜i"aÆ"'[D]"'éaÆ''+ƒkΣR
''j insert an apostrophe between every pair of commands
"'[B]"'XaÆ"'[C]""k;╗i"aÆ"'[P]""╜i"aÆ"'[D]"'éaÆ replace:
"'[B]"'XaÆ "'[B]" with "X"
"'[C]""k;╗i"aÆ "'[C]" with "k;╗i"
"'[P]""╜i"aÆ "'[P]" with "╜i"
"'[D]"'éaÆ "'[D]" with "é"
''+ prepend an apostrophe
now the input has been converted to the equivalent Actually program ("'<character>" pushes the character, "X" removes the last character, "k;╗i" saves the current stack state to a register, and "╜i" pushes the saved stack state)
ƒ execute the code
kΣ concatenate the characters
R reverse the string

Explanation

v % Push empty array
XK % Copy to clipboard K. This initiallizes it as empty
x % Delete
" % Implicitly input cell array. For each
@g % Push current cell's contents
t % Duplicate elements
n % Number of elements
q? % If more then 1
2) % Get second char. Copy to clipboard J
66=? % If it ss 'B'
3L) % Remove last element from string built up to now
} % Else
J67=? % If it was a 'C'
XK % Copy string built up to now into clipboard K
} % Else
J68=? % If was a 'D'
vx % Delete stack. This deletes string built up to now, if any
} % Else: it was a 'P'
K % Paste from clipboard K
] % End if
] % End if
] % End if
] % End if
&h % Horizontally concatenate stack
% Implicitly end for
% Implicitly display

Explanation

for(
;
n|$i=$argv[++$x]; # Iterates over the input until null.
)
($l=$i[1])? # Check if this item is a command, if so set to $l
$l^r? # If the command is not B
$l^s? # If the command is not C
$l^t? # If the command is not D
$o.=$c # Then it's P, so paste the clipboard ($c)
:$o="" # It's D, so delete output
:$c=$o # It's C, so copy output to clipboard
:$o[-1]="" # It's B, so remove the last output char
:$o.=$i; # No command, add the current item to the output.
echo$o; # Print the output.

Tweaks

Saved 3 bytes by combining the output handling with the command handling

Your Answer

If this is an answer to a challenge…

…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.

…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.

…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.

More generally…

…Please make sure to answer the question and provide sufficient detail.

…Avoid asking for help, clarification or responding to other answers (use comments instead).

Code Golf Stack Exchange is a site for recreational programming competitions, not general programming questions. Challenges must have an objective scoring criterion, and it is highly recommended to first post proposed challenges in the Sandbox.