next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: El Hash %item Sup: RecDescent Ant: Utilizando score Err: Si hallas una errata ...

Usando autoscore

La solución anterior puede simplificarse usando autoscore. Si una directiva <autoscore> aparece en cualquier producción de una variable sintáctica, el código especificado por la misma es utilizado como código para la puntuación de la producción dentro de las producciones de la variable sintáctica. Con la excepción, claro está, de aquellas reglas que tuvieran ya una directiva score explícitamente asignada. El código de la gramática queda como sigue:
my $grammar = q{
  line : <autoscore: @{$item[1]}>
       | <leftop: value ',' value> 
       | <leftop: datum ':' datum> 
       | <leftop: field ";" field> 
        
  value: /[^,]*/ 
  datum: /[^:]*/ 
  field: /[^;]*/ 
};

Por defecto, el analizador generado por parse::RecDescent siempre acepta la primera producción que reconoce un prefijo de la entrada. Como hemos visto, se puede cambiar esta conducta usando la directiva <score: ...>. Las diferentes producciones son intentadas y su puntuación (score) evaluada, considerándose vencedora aquella con mayor puntuación. Esto puede usarse para hacer que la regla vencedora sea ``la mas larga'', en el sentido de ser la que mas elementos en @item deja. En este caso tomamos ventaja de la directiva <autoscore>, la cual permite asociar una directiva <score> con cada producción que no tenga ya una directiva <score> explícita.

#!/usr/local/bin/perl5.8.0 -w 
use strict;
use warnings;
use Parse::RecDescent;

$::RD_TRACE = 1;
#$::RD_HINT = 1;
my $grammar = q {

  start:  seq_1 ';'
  seq_1     : <autoscore: @item>
            | 'A' 'B' 'C' 'D'
               { local $^W = 0; 
                 print "seq_1: " . join (" ", @item[1..$#item]) . " score: $score\n" 
               }
            |  'A' 'B' 'C' 'D' 'E' 'F'
               { print "seq_1: " . join (" ", @item[1..$#item]) . " score: $score\n" }
};

my $parser;

{
  local $^W = 0; # Avoid warning "uninitialized value in (m//) at RecDescent.pm line 626."
  $parser=Parse::RecDescent->new($grammar);
}

my $result = $parser->start("A B C D E F ;");
if (defined($result)) { 
  print "Valida\n";
} else { print "No reconocida\n"; }


next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: El Hash %item Sup: RecDescent Ant: Utilizando score Err: Si hallas una errata ...
Casiano Rodríguez León
2012-05-22