Subsecciones

Renombrando los resultados de una subregla

Nombre de la regla versus Nombre del Resultado

No siempre el nombre de la regla es el mas apropiado para ser el nombre del resultado:

It is not always convenient to have subrule results stored under the same name as the rule itself. Rule names should be optimized for understanding the behaviour of the parser, whereas result names should be optimized for understanding the structure of the data. Often those two goals are identical, but not always; sometimes rule names need to describe what the data looks like, while result names need to describe what the data means.

Colisión de nombres de reglas

For example, sometimes you need to call the same rule twice, to match two syntactically identical components whose positions give then semantically distinct meanings:

    <rule: copy_cmd>
        copy <file> <file>

The problem here is that, if the second call to <file> succeeds, its result-hash will be stored under the key file, clobbering the data that was returned from the first call to <file>.

Aliasing

To avoid such problems, Regexp::Grammars allows you to alias any subrule call, so that it is still invoked by the original name, but its result-hash is stored under a different key. The syntax for that is: <alias=rulename>. For example:

    <rule: copy_cmd>
        copy <from=file> <to=file>

Here, <rule: file> is called twice, with the first result-hash being stored under the key from, and the second result-hash being stored under the key to.

Note, however, that the alias before the = must be a proper identifier (i.e. a letter or underscore, followed by letters, digits, and/or underscores). Aliases that start with an underscore and aliases named MATCH have special meaning.

Normalización de los resultados mediante aliasing

Aliases can also be useful for normalizing data that may appear in different formats and sequences. For example:

    <rule: copy_cmd>
        copy <from=file>        <to=file>
      | dup    <to=file>  as  <from=file>
      |      <from=file>  ->    <to=file>
      |        <to=file>  <-  <from=file>

Here, regardless of which order the old and new files are specified, the result-hash always gets:

    copy_cmd => {
        from => 'oldfile',
          to => 'newfile',
    }

Ejemplo

El siguiente programa ilustra los comentarios de la documentación:

pl@nereida:~/Lregexpgrammars/demo$ cat -n copygrammar.pl
     1  use strict;
     2  use warnings;
     3  use 5.010;
     4  use Data::Dumper;
     5
     6  my $rbb = do {
     7      use Regexp::Grammars;
     8      qr{
     9        <copy_cmd>
    10
    11        <rule: copy_cmd>
    12              copy <from=file> <to=file>
    13          |   <from=file> ->   <to=file>
    14          |   <to=file>   <- <from=file>
    15
    16        <token: file> [\w./\\]+
    17      }x;
    18  };
    19
    20  while (my $input = <>) {
    21      while ($input =~ m{$rbb}g) {
    22          say("matches: <$&>");
    23          say Dumper \%/;
    24      }
    25  }
Cuando lo ejecutamos obtenemos:
pl@nereida:~/Lregexpgrammars/demo$ perl5.10.1 copygrammar.pl
copy a b
matches: <copy a b>
$VAR1 = {
          '' => 'copy a b',
          'copy_cmd' => {
                          '' => 'copy a b',
                          'to' => 'b',
                          'from' => 'a'
                        }
        };

b <- a
matches: <b <- a>
$VAR1 = {
          '' => 'b <- a',
          'copy_cmd' => {
                          '' => 'b <- a',
                          'to' => 'b',
                          'from' => 'a'
                        }
        };

a -> b
matches: <a -> b>
$VAR1 = {
          '' => 'a -> b',
          'copy_cmd' => {
                          '' => 'a -> b',
                          'to' => 'b',
                          'from' => 'a'
                        }
        };

Casiano Rodríguez León
2009-12-09