regex

とりあえずhatenaのソースコード表示が気に食わないので、タグ付けスクリプトを考え始めたのはいいが、気付いたら正規表現のみでなんとかする大会が始まっていた。でその途中経過が下のやつ。とりあえずコメント以外はなんとなく処理できる。ただエスケープシーケンスの処理は怪しい。多分行末に\があると正しく動作しない。もうちょっとスマートに書けそうなもんだが、所詮かじっただけの知識ではこの程度が限界である。あとあんまり関係ないけどゴルフしてる人はすげーなって思った。


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

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

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

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

# character
# /[^"'\\]|\\./
$c_char = qq/[^"'\\\\]|\\\\./;

$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|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)";

# keywords
s%\G((?:(?:$c_char)|"(?:'|$c_char)*?"|'(?:"|$c_char)*?')*?)\b($keywords)\b%\1<span class="keywords">\2</span>%xg;

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

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

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

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

print '<pre class="c++">\n';
print;
print "</pre>\n";

あ、改行って\nでできるやん。あとclass名がC++だと、cssに.C\+\+とか書かんとあかんな。