

[4] para una descripción de como hacerlo). En lo que sigue, y por brevedad,
nos referiremos a el como RD.
1 #!/usr/local/bin/perl5.8.0 -w
2 use strict;
3 use warnings;
4
5 use Parse::RecDescent;
6
7
8 my $grammar = q {
9
10 start: seq_1 seq_2
11
12 seq_1 : 'A' 'B' 'C' 'D'
13 { print "seq_1: " . join (" ", @item[1..$#item]) . "\n" }
14 | 'A' 'B' 'C' 'D' 'E' 'F'
15 { print "seq_1: " . join (" ", @item[1..$#item]) . "\n" }
16
17 seq_2 : character(s)
18
19 character: /\w/
20 { print "character: $item[1]\n" }
21
22 };
23
24 my $parser=Parse::RecDescent->new($grammar);
25
26 $parser->start("A B C D E F");
En la línea 5 se declara el uso del módulo.
En la línea 8 se guarda la gramática en la variable escalar
$grammar.
La variable sintáctica start es considerada de arranque de la gramática.
Las partes derechas de las producciones se separan mediante la barra |,
y las acciones se insertan entre llaves.
El contenido de las acciones es código Perl.
Dentro de esas acciones es posible
hacer alusión a los atributos de los símbolos de la producción a través
del array @item. Así $item[1] contendrá el atributo asociado
al primer símbolo (el carácter A en este caso).
Para que una producción tenga éxito es necesario
que la acción devuelva un valor definido (no necesariamente verdadero).
El valor asociado con una producción es el valor retornado por
la acción, o bien el valor asociado con la variable $return
(si aparece en la acción)
o con el item asociado con el último símbolo que casó con éxito.
Es posible indicar una o mas repeticiones de una forma sentencial como en la línea 17. La regla:
seq_2 : character(s)
indica que el lenguaje seq_2 se forma por la repetición de uno
o mas caracteres (character). El valor
asociado con una pluralidad de este tipo es una referencia a un array
conteniendo los valores individuales de cada uno de los elementos que
la componen, en este caso de los character.
Es posible introducir un patrón de separación que
indica la forma en la que se deben separar los elementos:
seq_2 : character(s /;/)
lo cual especifica que entre character y character
el analizador debe saltarse un punto y coma.
Como se ve en la línea 19 es legal usar expresiones regulares
en la parte derecha. La llamada al constructor en la línea 24
deja en $parser un analizador sintáctico recursivo descendente.
El analizador así construido dispone de un método por cada una de
las variables sintácticas de la gramática. El método asociado con una
variable sintáctica reconoce el lenguaje generado por esa variable sintáctica.
Así, la llamada de la línea 26 al método start
reconoce el lenguaje generado por start.
Si la variable sintáctica tiene éxito el método
retorna el valor asociado. En caso contrario
se devuelve undef. Esto hace posible
retornar valores como 0, "0", or "".
La siguiente ejecución muestra el orden de recorrido de las producciones.
$ ./firstprodnolongest.pl seq_1: A B C D character: E character: F
¿Que ha ocurrido?
RD es perezoso en la evaluacion de las producciones.
Como la primera regla tiene éxito y es evaluada antes que la segunda,
retorna el control a la aprte derecha de la regla de start.
A continuación se llama a seq2.
En este otro ejemplo invertimos el orden de las reglas
de producción de seq_1:
#!/usr/local/bin/perl5.8.0 -w
use strict;
use warnings;
use Parse::RecDescent;
my $grammar = q {
start: seq_1 seq_2
seq_1 : 'A' 'B' 'C' 'D' 'E' 'F'
{ print "seq_1: " . join (" ", @item[1..$#item]) . "\n" }
| 'A' 'B' 'C' 'D'
{ print "seq_1: " . join (" ", @item[1..$#item]) . "\n" }
seq_2 : character(s)
character: /\w/
{ print "character: $item[1]\n" }
};
my $parser=Parse::RecDescent->new($grammar);
$parser->start("A B C D E F");
La ejecución resultante da lugar al éxito de la primera regla, que absorbe
toda la entrada:
$ ./firstprodnolongest2.pl seq_1: A B C D E F

