2011-07-07 11 views
13

私は、アセンブリ命令の文字列を32ビットのバイナリコードに変換する単純なPerlスクリプトを書いています。正規表現/(ab)?use /:それよりも複雑な表現はありますか?

私はタイプによって翻訳グループ化する命令を処理することを決定した(ADDSUBがそうでRタイプの命令であり、...)ので、私のコードで私はこのような何かやっている:私はので

my $bin = &r_type($instruction) if $instruction =~ /^(?:add|s(?:ub|lt|gt))\s/; 

を同じようにaddsubsltおよびsgtを処理します。

私は多分、正規表現は、私が行うことになってるタスクのための「やり過ぎ」であることができることを利用していること...パターン

/^(?:add|sub|slt|sgt)\s/ 

は、この中の正規表現の活用を表すことができしかし、実現場合?

ありがとうございます。

+2

この場合、オペコードのリストは、読み込みの方がはるかに明確です。交互に使用してください。 –

答えて

22

5.10より前のperlを使用していない限り、単純な変更はとにかく実行します(here参照)。そのため、最適化を試みる理由はありません。

+1

ありがとうございます、リンクの+1。 – dave

4

2番目のバージョンは、よりシンプルで読みやすく、メンテナンス性に優れています。パフォーマンスの差は正規表現の実装に依存しますが、ネストされたバージョンは複雑さが増してゆっくりと実行されると思われます。

はい、それは過剰です。

5

正規表現に埋め込まれたニーモニックを配置する代わりに、ハッシュを使用してディスパッチテーブルを作成します。従って、少なくとも同等に、より速く、あなたのコードはるかに容易になります。

my %emitter = (add => \&r_type, 
       sub => \&r_type, 
       slt => \&r_type, 
       sgt => \&r_type, 
       ...); 

if ($instruction =~ /^(\S+)/) { 
    my $emitter = $emitter{$1} // die "bad instruction $instruction"; 
    $emitter->($1, $istruction); 
} 
else { 
    # error?... 
} 
+1

非常に良いアプローチ!アドバイスありがとうございます:) – dave

5

私は(私はPerlのマスタリングのそれの多くを示して)salva's dispatch tableを好きですが、私は質問の別の側面にお答えしますあなたはいつか別の問題の答えが必要です。

あなたが入れ子にされるかもしれないそのうちのいくつかは、いくつかの交替を、構築したいとき、あなたは醜い正規表現の構文を見ていないので、あなたのための交代を構築するためにRegexp::Trieのようなものを使用することができます。

use Regexp::Trie; 
my $rt = Regexp::Trie->new; 

foreach (qw/add sub slt sgt/) { 
    $rt->add($_); 
    } 

print $rt->regexp, "\n"; 

(?-xism:(?:add|s(?:gt|lt|ub))) 

このようにして、Jonathanの提案のようなオペコードをリストアップするだけでなく、代替を得ることもできます。 ysthが指摘しているように、あなたは今やとにかくこれをPerlで無料で入手できるかもしれません。

+1

ありがとう、私はそれを念頭に置くよ! (...私の夏の読書を見つけた...;)) – dave