13 Stimmen

Regulärer Ausdruck /(ab)?use/: Lohnt sich ein komplexerer Ausdruck?

Ich schreibe ein einfaches Perl-Skript, das Assembler-Befehlszeichenfolgen in 32-Bit-Binärcode übersetzt.

Ich habe beschlossen, die Übersetzung nach Typ zu gruppieren ( ADD y SUB sind R-Type-Anweisungen und so weiter...), also mache ich in meinem Code so etwas wie das hier:

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

denn ich möchte mit add , sub , slt y sgt auf dieselbe Weise.

Mir wurde jedoch klar, dass die Verwendung dieses regulären Ausdrucks für die Aufgabe, die ich erledigen soll, vielleicht zu viel des Guten ist... könnte das Muster

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

in diesem Fall eine bessere Verwendung von regulären Ausdrücken darstellen?

Herzlichen Dank.

22voto

ysth Punkte 91645

Sofern Sie nicht ein Perl älter als 5.10 verwenden, wird die einfache Alternation ohnehin besser funktionieren (siehe aquí ), so dass es keinen Grund gibt, sie zu optimieren.

5voto

salva Punkte 9683

Anstatt die Mnemonics in regulären Ausdrücken zu platzieren, erstellen Sie eine Dispatch-Tabelle mit einem Hash. Das ist mindestens genauso schnell und Ihr Code ist viel übersichtlicher:

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?...
}

5voto

brian d foy Punkte 124323

Ich mag Salva's Versandtisch (Ich zeige eine Menge davon in Perl beherrschen ), aber ich werde einen anderen Aspekt der Frage beantworten, falls Sie diese Antwort eines Tages für ein anderes Problem benötigen.

Wenn Sie einige Abwandlungen erstellen wollen, von denen einige verschachtelt sein könnten, können Sie etwas verwenden wie Regexp::Trie um die Abwechslung für Sie zu erstellen, damit Sie nicht auf die hässliche Regex-Syntax schauen müssen:

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

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

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

Das gibt Ihnen:

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

Auf diese Weise können Sie die Opcodes auflisten, wie Jonathan es vorgeschlagen hat, aber auch die Abwechslung erhalten. Wie ysth bemerkte, könnte man dies mit Perl jetzt sowieso kostenlos bekommen.

4voto

peterjwest Punkte 4018

Ihre zweite Version ist einfacher, besser lesbar und leichter zu pflegen. Der Leistungsunterschied wird von der Regex-Implementierung abhängen, aber ich vermute, dass die verschachtelte Version aufgrund ihrer höheren Komplexität langsamer laufen wird.

Ja, das ist zu viel des Guten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X