2011-07-07 8 views
13

Estoy escribiendo un script Perl simple que traduce cadenas de instrucciones de ensamblaje a código binario de 32 bits.Expresión regular/(ab)? Use /: ¿Vale la pena una expresión más compleja?

decidí manejar la instrucción agrupación por tipo de traducción (ADD y SUB son instrucciones de tipo R y así sucesivamente ...) por lo que en mi código que estoy haciendo algo como esto:

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

porque quieren manejar add, sub, slt y sgt de la misma manera.

sin embargo, me di cuenta de que tal vez usando esa expresión regular podría ser una 'exageración' para la tarea que tengo que hacer ... ¿podría el patrón

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

represento un mejor uso de expresiones regulares en este ¿caso?

Muchas gracias.

+2

En este caso, una lista de los códigos de operación es mucho más claro para la lectura. Usa las alternancias. –

Respuesta

22

A menos que esté usando un perl anterior a 5.10, la alternancia simple tendrá un mejor rendimiento de todos modos (consulte here), por lo que no hay ninguna razón para intentar optimizarlo.

+1

Gracias, +1 por el enlace. – dave

4

Su segunda versión es más simple, más fácil de leer y más fácil de mantener. La diferencia de rendimiento dependerá de la implementación de expresiones regulares, pero sospecho que la versión anidada se ejecutará más lentamente debido a su mayor complejidad.

Sí, es una exageración.

5

En lugar de colocar los mnemónicos enterrados dentro de expresiones regulares, construir una tabla de despacho utilizando un hash. Será por lo menos igual de rápido y su código mucho más fácil de seguir:

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

Muy buen enfoque! Gracias por el consejo :) – dave

5

me gusta salva's dispatch table (muestro mucho de eso en Mastering Perl), pero voy a responder a otro aspecto de la cuestión en Si necesita una respuesta para un problema diferente algún día.

Cuando se quiere construir algunas alternancias, algunos de los cuales podrían ser anidadas, puede usar algo como Regexp::Trie para construir la alternancia para usted de modo que no se ven en la sintaxis de expresiones regulares fea:

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

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

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

Eso le da:

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

De esta manera, usted enumera los códigos de operación como Jonathan sugirió, pero también consigue la alternancia. Como ya se dijo, puede obtener esto gratis con Perl ahora de todos modos.

+1

Muchas gracias, lo tendré en cuenta! (... y encontré mi lectura de verano ...;)) – dave