next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Las directivas rulevar y Sup: RecDescent Ant: La directiva commit Err: Si hallas una errata ...

Las Directivas skip y leftop

Consideremos una extensión al conocido problema del reconocimietno del lenguaje de valores separados por comas (véase la sección 3.4.3). El fichero de entrada contiene líneas como esta:

"tierra, luna",1,"marte, deimos",9.374

la extensión consiste en admitir que el separador puede cambiar entre líneas y en los campos de una línea, pudiendo ser no sólo la coma sino también un tabulador o el carácter dos puntos. El problema está en que los separadores dentro de las cadenas no deben confundirnos. Por ejemplo, la coma en "tierra, luna" no debe ser interpretada como un separador.

He aqui una solución usando RD:

 1 #!/usr/local/bin/perl5.8.0 -w
 2 use strict;
 3 use Parse::RecDescent;
 4 use Data::Dumper;
 5 
 6 my $grammar = q{
 7   line : <leftop: value sep value> 
 8   value: /"([^"]*)"/ { $1; }
 9   sep : <skip:""> /[:,\t]/
10 };
11 
12 my $parse = Parse::RecDescent->new($grammar);
13 
14 my $line;
15 while ($line = <>) {
16   print "$line\n";
17   my $result = $parse->line($line);
18   print Dumper($result);
19 }

La directiva <skip> usada en la línea 9 permite redifinir lo que el analizador entiende por ``blancos'': los símbolos sobre los que saltar. Por defecto el tabulador es un ``blanco''. En este ejemplo, cuando estamos reconociendo un separador no queremos que sea así. La directiva <skip:""> hace que ningún símbolo sea considerado como blanco.

La directiva usada en la línea 7 <leftop: value sep value> especifica una lista asociativa a izquierdas de elementos de tipo value separados por elementos del lenguaje denotado por sep. El valor retornado es un array anónimo conteniendo la lista de elementos. En general, si el separador es especificado como una cadena, la directiva no retorna el separador como parte de la lista. Por ejemplo, en el código:

list: '(' <leftop: list_item ',' list_item> ')' { $return = $item[2] }

el valor devuelto es una referencia a la lista, la cual no incluye las comas. Sin embargo, cuando el separador viene dado por una variable sintáctica o bien por medio de una expresión regular, las distintas apariciones del separador se incluyen en la lista devuelta. Este es el caso en nuestro ejemplo.

Veamos primero el fichero de entrada para la ejecución:

$ cat file.txt
"xx":"yyy":"zzz"
"xx","yyy","zzz"
"xx"    "yyy"   "zzz"
"xx"    "yyy","zzz"
"xx":"yyy","zzz"
"x:x":"y,y","z  zz"
"x:x":"y,y","z  zz"."ttt"
La última fila usa el punto como separador del último campo. La ejecución de Dumper($result) en la línea 18 nos muestra las listas formadas:
$ ./commaseparated.pl file.txt
"xx":"yyy":"zzz"
$VAR1 = [ 'xx', ':', 'yyy', ':', 'zzz' ];
"xx","yyy","zzz"
$VAR1 = [ 'xx', ',', 'yyy', ',', 'zzz' ];
"xx"    "yyy"   "zzz"
$VAR1 = [ 'xx', '     ', 'yyy', '     ', 'zzz' ];
"xx"    "yyy","zzz"
$VAR1 = [ 'xx', '     ', 'yyy', ',', 'zzz' ];
"xx":"yyy","zzz"
$VAR1 = [ 'xx', ':', 'yyy', ',', 'zzz' ];
"x:x":"y,y","z  zz"
$VAR1 = [ 'x:x', ':', 'y,y', ',', 'z  zz' ];
"x:x":"y,y","z  zz"."ttt"
$VAR1 = [ 'x:x', ':', 'y,y', ',', 'z  zz' ];
La última entrada "x:x":"y,y","z zz"."ttt" muestra como el analizador se detiene en la cadena máximal "x:x":"y,y","z zz" que pertenece al lenguaje.

Ejercicio 6.5.1   La última salida del programa anterior no produce un rechazo de la cadena de entrada. Se limita a detenerse en la cadena máximal "x:x":"y,y","z zz" que puede aceptar. Si queremos que la conducta sea de rechazo, se puede hacer que sea la línea completa la que se empareje. Escriba una nueva versión del programa anterior que recoja esta especificación.

Ejercicio 6.5.2   Escriba una variante del ejercicio anterior en la que se fuerze a que todos los separadores en una misma línea sean iguales (aunque pueden ser diferentes en diferentes líneas).


next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Las directivas rulevar y Sup: RecDescent Ant: La directiva commit Err: Si hallas una errata ...
Casiano Rodríguez León
2013-03-05