2012-02-20 10 views
6

Al analizar texto, frecuentemente necesito implementar mini-máquinas-estado, en forma genérica siguiendo el siguiente código.¿Hay un buen módulo de CPAN para implementar máquinas de estado al analizar texto?

¿Hay un módulo CPAN que se considera "mejor práctica" y muy adecuado para implementar la lógica máquina de estados como esto de una manera fácil y elegante?

yo preferiría soluciones menos complicado que Parse::RecDescent pero si no existe ninguno y Parse::RecDescent es mucho más fácil de aplicar a este problema de lo que pensaba, estoy muy dispuesto a considerarlo en vez de rodar mi propia como si hubiera estado tan lejos.

ejemplo genérico código de análisis:

my $state = 1; 
while (my $token = get_next_token()) { # Usually next line 
    if ($state == 1) { 
     do_state1_processing(); 
     if (token_matches_transition_1_to_2($token)) { 
      do_state_1_to_2_transition_processing(); 
      $state == 2; 
      next; 
     } elsif (token_matches_transition_1_to_4($token)) { 
      do_state_1_to_4_transition_processing(); 
      $state == 4; 
      next; 
     } else { 
      do_state1_continuation(); 
      next; 
     } 
    } elsif ($state == 5) { 
     do_state5_processing(); 
     if (token_matches_transition_5_to_6($token)) { 
      do_state_5_to_6_transition_processing(); 
      $state == 6; 
      next; 
     } elsif (token_matches_transition_5_to_4($token)) { 
      do_state_5_to_4_transition_processing(); 
      $state == 4; 
      next; 
     } else { 
      do_state5_continuation(); 
      next; 
     } 
    } else { 

    } 

} 
+3

¿Qué hay de 'FSA :: Rules'? (los módulos 'DFA :: *' mencionados [aquí] (http://www.perl.com/pub/2004/09/23/fsms.html) podrían ser otra ventaja). – Ouki

+3

Yo mismo usaría un hash de subs devolviendo el siguiente estado en tal caso. Sin embargo, me gustaría ver qué más se puede usar, también. – Dallaylaen

+0

@Dallaylaen: mi pensamiento exactamente, pero DVK pidió un módulo;) – Ouki

Respuesta

3

lo recomiendo echar un vistazo a Marpa y Marpa::XS.

Basta con mirar a this simple calculator.

my $grammar = Marpa::XS::Grammar->new(
    { start => 'Expression', 
     actions => 'My_Actions', 
     default_action => 'first_arg', 
     rules => [ 
      { lhs => 'Expression', rhs => [qw'Term'] }, 
      { lhs => 'Term', rhs => [qw'Factor'] }, 
      { lhs => 'Factor', rhs => [qw'Number'] }, 
      { lhs => 'Term', rhs => [qw'Term Add Term'], action => 'do_add' }, 
      { lhs => 'Factor', 
       rhs => [qw'Factor Multiply Factor'], 
       action => 'do_multiply' 
      }, 
     ], 
    } 
); 

Deberá implementar el tokenizador usted mismo.

+1

al analizar las unidades de matemáticas usando Marpa: https://github.com/jberger/Math-ParseUnit –

2

Puede utilizar Class::StateMachine:

package Foo; 
use parent 'Class::StateMachine'; 

sub new { 
    my $class = shift; 
    Class::StateMachine::bless {}, $class, 'state_1'; 
} 

sub do_state_processing :OnState('state_1') { 
    my $self = shift; 
    if (...) { $self->event_1 } 
    elsif (...) { $self->event_2 } 
    ... 
} 

sub do_state_processing :OnState('state_2') { 
    ... 
} 

sub event_1 :OnState('state_1') { 
    my $self = shift; 
    $self->state('state_2'); 
} 

sub event_2 :OnState('state_2') { 
    my $self = shift; 
    $self->state('state_3'); 
} 

sub enter_state :OnState('state_1') { 
    print "entering state 1"; 
    ... 
} 

sub enter_state :OnState('state_2') { 
    ... 
} 

package main; 

my $sm = Foo->new; 
... 
while (my $token = get_next_token()) { 
    $sm->do_state_processing; 
} 

embargo, un módulo específico para el procesamiento de texto, probablemente será más adecuado para su caso particular

1

(con ayuda) Yo he escrito hace unos años se llama el Perl Formal Language Toolkit así que esto podría servir como una especie de base, sin embargo lo que creo que realmente queremos es una herramienta como el Ragel Finite State Machine Compiler. Por desgracia, no lo hace de salida a Perl, y es un deseo quemador vertebral de la mina para implementar un objetivo Perl para Ragel y proporcionar también similar (pero más orientado Perl) presenta para mi módulo de bits en descomposición.

0

escribí Parser::MGC sobre todo porque me encontré tratando de conseguir Parse::RecDescent a hacer el informe de errores apropiado era bastante difícil, y yo no les gustaba su extraña gramática incrustado costumbre entre comillas de cadena que contienen código Perl, junto con el otro código Perl. Un programa P::MGC es solo código perl; pero escrito como un descenso recursivo en la estructura gramatical similar a P::RD.

Cuestiones relacionadas