La directiva require

La directiva require es similar en su funcionamiento al paréntesis 5.10 (??{ Código Perl }) el cuál hace que el Código Perl sea evaluado durante el tiempo de matching. El resultado de la evaluación se trata como una expresión regular con la que deberá casarse. (véase la sección 1.2.9 para mas detalles).

La sintáxis de la directiva <require:> es

                        <require: (?{ CODE }) >

The code block is executed and if its final value is true, matching continues from the same position. If the block's final value is false, the match fails at that point and starts backtracking.

The <require:...> directive is useful for testing conditions that it's not easy (or even possible) to check within the syntax of the the regex itself. For example:

    <rule: IPV4_Octet_Decimal>
        # Up three digits...
        <MATCH= ( \d{1,3}+ )>
        
        # ...but less that 256...
        <require: (?{ $MATCH <= 255 })>

A require expects a regex codeblock as its argument and succeeds if the final value of that codeblock is true. If the final value is false, the directive fails and the rule starts backtracking.

Note, in this example that the digits are matched with \d{1,3}+ . The trailing + prevents the {1,3} repetition from backtracking to a smaller number of digits if the <require:...> fails.

El programa demo_IP4.pl ilustra el uso de la directiva:

pl@nereida:~/Lregexpgrammars/demo$ cat -n ./demo_IP4.pl
 1  #!/usr//bin/env perl5.10.1
 2  use v5.10;
 3  use warnings;
 4
 5  use Regexp::Grammars;
 6
 7  my $grammar = qr{
 8      \A <IP4_addr> \Z
 9
10      <token: quad>
11          <MATCH=(\d{1,3})>
12          <require: (?{ $MATCH < 256 })>
13
14      <token: IP4_addr>
15          <[MATCH=quad]>**(\.)
16          <require: (?{ @$MATCH == 4 })>
17  }xms;
18
19  while (my $line = <>) {
20      if ($line =~ $grammar) {
21          use Data::Dumper 'Dumper';
22          say Dumper \%/;
23      }
24      else {
25          say 'Does not match'
26      }
27  }
Las condiciones usadas en el require obligan a que cada quad1.9 sea menor que 256 y a que existan sólo cuatro quads.

Sigue un ejemplo de ejecución:

pl@nereida:~/Lregexpgrammars/demo$ ./demo_IP4.pl
123 . 145 . 105 . 252
Does not match
pl@nereida:~/Lregexpgrammars/demo$ ./demo_IP4.pl
123.145.105.252
$VAR1 = {
          '' => '123.145.105.252',
          'IP4_addr' => [
                          123,
                          145,
                          105,
                          252
                        ]
        };
pl@nereida:~/Lregexpgrammars/demo$ ./demo_IP4.pl
148.257.128.128
Does not match
0.0.0.299
Does not match
pl@nereida:~/Lregexpgrammars/demo$  ./demo_IP4.pl
123.145.105.242.193
Does not match
Obsérvese como no se aceptan blancos entre los puntos en esta versión. ¿Sabría explicar la causa?

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