Aliases can also be given to standard Perl subpatterns, as well as to code blocks within a regex. The syntax for subpatterns is:
<ALIAS= (SUBPATTERN) >
In other words, the syntax is exactly like an aliased subrule call, except that the rule name is replaced with a set of parentheses containing the subpattern. Any parentheses-capturing or non-capturing-will do.
The effect of aliasing a standard subpattern is to cause whatever that subpattern matches to be saved in the result-hash, using the alias as its key. For example:
<rule: file_command> <cmd=(mv|cp|ln)> <from=file> <to=file>
Here, theSigue un ejemplo:<cmd=(mv|cp|ln)>
is treated exactly like a regular(mv|cp|ln)
, but whatever substring it matches is saved in the result-hash under the key'cmd'
.
pl@nereida:~/Lregexpgrammars/demo$ cat -n subpattern.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 9 qr{ 10 <file_command> 11 12 <rule: file_command> 13 14 <cmd=(mv|cp|ln)> <from=([\w./]+)> <to=([\w./]+)> 15 16 }x; 17 }; 18 19 while (my $input = <>) { 20 while ($input =~ m{$rbb}g) { 21 say("matches: <$&>"); 22 say Dumper \%/; 23 } 24 }y una ejecución:
pl@nereida:~/Lregexpgrammars/demo$ perl5.10.1 subpattern.pl mv a b matches: <mv a b> $VAR1 = { '' => 'mv a b', 'file_command' => { '' => 'mv a b', 'to' => 'b', 'cmd' => 'mv', 'from' => 'a' } }; cp c d matches: <cp c d> $VAR1 = { '' => 'cp c d', 'file_command' => { '' => 'cp c d', 'to' => 'd', 'cmd' => 'cp', 'from' => 'c' } }
The syntax for aliasing code blocks is:
<ALIAS= (?{ your($code->here) }) >
Note, however, that the code block must be specified in the standard
Perl 5.10 regex notation: (?{...})
. A common mistake is to write:
<ALIAS= { your($code->here } >
instead, which will attempt to interpolate$code
before the regex is even compiled, as such variables are only protected from interpolation inside a(?{...})
.
When correctly specified, this construct executes the code in the block
and saves the result of that execution in the result-hash, using the
alias as its key. Aliased code blocks are useful for adding semantic
information based on which branch of a rule is executed. For example,
consider the copy_cmd
alternatives shown earlier:
<rule: copy_cmd> copy <from=file> <to=file> | dup <to=file> as <from=file> | <from=file> -> <to=file> | <to=file> <- <from=file>
Using aliased code blocks, you could add an extra field to the result- hash to describe which form of the command was detected, like so:
<rule: copy_cmd> copy <from=file> <to=file> <type=(?{ 'std' })> | dup <to=file> as <from=file> <type=(?{ 'rev' })> | <from=file> -> <to=file> <type=(?{ 'fwd' })> | <to=file> <- <from=file> <type=(?{ 'bwd' })>
Now, if the rule matched, the result-hash would contain something like:
copy_cmd => { from => 'oldfile', to => 'newfile', type => 'fwd', }
El siguiente ejemplo ilustra lo dicho en la documentación. En la línea 15 hemos introducido una regla para el control de errores3.8:
pl@nereida:~/Lregexpgrammars/demo$ cat -n aliasedcodeblock2.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>) <type=(?{ 'std' })> 13 | <from=file> -> <to=file> <type=(?{ 'fwd' })> 14 | <to=file> <- <from=file> <type=(?{ 'bwd' })> 15 | .+ (?{ die "Syntax error!\n" }) 16 17 <token: file> [\w./\\]+ 18 }x; 19 }; 20 21 while (my $input = <>) { 22 while ($input =~ m{$rbb}g) { 23 say("matches: <$&>"); 24 say Dumper \%/; 25 } 26 }
La ejecución muestra el comportamiento del programa con tres entradas válidas y una errónea:
pl@nereida:~/Lregexpgrammars/demo$ perl5.10.1 aliasedcodeblock2.pl copy a b matches: <copy a b > $VAR1 = { '' => 'copy a b ', 'copy_cmd' => { '' => 'copy a b ', 'to' => 'b', 'from' => 'a', 'type' => 'std' } }; b <- a matches: <b <- a > $VAR1 = { '' => 'b <- a ', 'copy_cmd' => { '' => 'b <- a ', 'to' => 'b', 'from' => 'a', 'type' => 'bwd' } }; a -> b matches: <a -> b > $VAR1 = { '' => 'a -> b ', 'copy_cmd' => { '' => 'a -> b ', 'to' => 'b', 'from' => 'a', 'type' => 'fwd' } }; cp a b Syntax error!
Note that, in addition to the semantics described above, aliased subpatterns and code blocks also become visible to Regexp::Grammars integrated debugger (see Debugging).