でけた


do {
$tmp = <STDIN>;
$_ .= $tmp;
} while ($tmp);

# & -> &amp;
s/&/&amp;/g;

# < -> &lt;
s/</&lt;/g;

# > -> &gt;
s/>/&gt;/g;

$keywords = "(auto|bool|catch|char|class|const|const_cast|do|double|dynamic_cast|enum|export|extern|float|for|goto|if|inline|int"
."|long|mutable|namespace|operator|private|protected|ptrdiff_t|public|register|reinterpret_cast|return|signed|size_t|sizeof|short"
."|static|static_cast|struct|template|this|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)";
$string = qq/"(?:[^"\\\\]|\\\\(?:.|\\n))"/;
$char = qq/'(?:[^'\\\\]|\\\\(?:.|\\n))'/;
$comment = qq%//(?:[^\\\\]|\\\\(?:.|\\n))*?\\n|/\\*(?:[^\\\\]|\\\\(?:.|\\n))*?\\*/%;

# keywords
s%((?:[^"'\\/]|\\.|/[^*/]|$comment|$string|$char)*?)\b($keywords)\b%\1<span class="keywords">\2</span>%xg;

# string
s%((?:[^"'<\\/]|\\.|/[^*/]|$comment|$char|<.*?>)*?)($string)%\1<span class="string">\2</span>%xg;

# char
s%((?:[^"'<\\/]|\\.|/[^*/]|$comment|$string|<.*?>)*?)($char)%\1<span class="char">\2</span>%xg;

# comment
s%((?:[^"'<\\/]|\\.|/[^*/]|$string|$char|<.*?>)*?)($comment)%\1<span class="comment">\2</span>%xg;

# <iostream>
s%(\n?[ ]*)(#[ ]*include)((?:[^\\<"']|\\.)*?)(&lt;(?:[^\\]|\\.)*?&gt;)%\1\2\3<span class="string">\4</span>%g;

# preprocess
s%(\n?[ ]*)(#[ ]*)(ifdef|ifndef|if|elif|else|endif|define|include|error|warning|pragma)\b%\1<span class="preprocess">\2\3</span>%g;

print qq/<pre class="cpp">\n/;
print;
print "</pre>\n";

こんなんでどう?
何時頃かに直上のコードをちょっと変更。相変わらず\の処理は適当。あとtypeid追加。忘れてた。
あと整数・浮動小数リテラルはTodoで。