next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Mensajes de Warning Sup: Análisis Sintáctico con Regexp::Grammars Ant: Depuración de Regexps Err: Si hallas una errata ...

Manejo y recuperación de errores

En este punto debo decir que no he podido reproducir el comportamiento de las directivas <error:> y <warning:> tal y como las describe Conway en el manual de Regexp::Grammars.

El siguiente ejemplo ilustra un conjunto de técnicas de gestión de errores que son independientes del soprote dado por Regexp::Grammars.

Se trata de la misma calculadora explicada en la sección 3.10.18.

pl@nereida:~/Lregexpgrammars/demo/calculator$ cat -n calculatorwitherrmanagement.pl
 1  #!/usr/bin/env perl5.10.1
 2  use strict;
 3  use warnings;
 4  use 5.010;
 5  use Lingua::EN::Inflect qw(PL);
 6  use Scalar::Util qw{blessed};
 7
 8  my $rbb = do {
 9      my ($warnings, $errors);    # closure
10      sub warnings { $warnings }  # accessor
11      sub errors { $errors }      # accessor
12
13      use Regexp::Grammars;
14      qr{
15        (?{
16            $warnings = 0;
17            $errors = 0;
18        })
19        \A<expr>
20        (?:   \z
21             |
22               (.*) (?{
23                        # Accept the string but emit a warning
24                        $warnings++;
25                        local our $expr = \$MATCH{expr}{''};
26                        local our $endlegal = length($$expr) > 4? "... ".substr($$expr, -4) : $$expr;
27                        warn "Warning: Unexpected '". substr($^N, 0, 10)."' after '$endlegal'\n";
28                     })
29        )
30
31        <objrule: expr>      <[operands=term]> ** <[operators=addop]>
32
33        <objrule: term>      <[operands=uneg]> ** <[operators=mulop]>
34
35        <objrule: uneg>      <[operators=minus]>* <[operands=power]>
36
37        <objrule: power>     <[operands=factorial]> ** <[operators=powerop]>
38
39        <objrule: factorial> <[operands=factor]>  <[operators=(!)]>*
40
41        <objrule: factor>    (<val=([+-]?\d+(?:\.\d*)?)>)
42                           | \( <MATCH=expr> \)
43                           | ([^-+(0-9]+) (?{
44                                            # is + and not * to avoid infinite recursion
45                                            warn "Error: expecting a number or a open parenthesis, found: '". substr($^N, 0, 10)."'\n";
46                                            $warnings++;
47                                            $errors++;
48                                        }) <MATCH=factor>
49
50        <token: addop>        [+-]
51
52        <token: mulop>        [*/]
53
54        <token: powerop>      \*\*|\^
55
56        <token: minus>        - <MATCH=(?{ 'NEG' })>
57
58      }x;
59  };
60
61  sub test_calc {
62    my $prompt = shift;
63
64    print $prompt;
65    while (my $input = <>) {
66        chomp($input);
67
68        local %/;
69        $input =~ m{$rbb};
70
71        say warnings." ".PL('warning',warnings) if warnings;
72        say errors." ".PL('error',errors)       if errors;
73
74        my $tree = $/{expr};
75        if (blessed($tree)) {
76            do "PostfixCalc.pm";
77            say "postfix: ".$tree->ceval;
78
79            do "EvalCalc.pm";
80            say "result: ".$tree->ceval;
81        }
82        print $prompt;
83    }
84    say "Bye!"
85  }
86
87  ########## main
88  test_calc(
89    'Parsing infix arithmetic expressions (CTRL-D to end in unix) ',
90  );

Veamos algunas ejecuciones que incluyen entradas erróneas:

pl@nereida:~/Lregexpgrammars/demo/calculator$ ./calculatorwitherrmanagement.pl
Parsing infix arithmetic expressions (CTRL-D to end in unix) 2+3
postfix: 2 3 +
result: 5
Parsing infix arithmetic expressions (CTRL-D to end in unix) 2*(3+#)
Error: expecting a number or a open parenthesis, found: '#)'
Error: expecting a number or a open parenthesis, found: '#'
Error: expecting a number or a open parenthesis, found: ')'
Warning: Unexpected '*(3+#)' after '2'
4 warnings
3 errors
postfix: 2
result: 2
Parsing infix arithmetic expressions (CTRL-D to end in unix) 2+#*4
Error: expecting a number or a open parenthesis, found: '#*'
1 warning
1 error
postfix: 2 4 +
result: 6
Parsing infix arithmetic expressions (CTRL-D to end in unix) Bye!
Obsérvese los mensajes de error repetidos para la entrada 2*(3+#). Ellos son debidos a los reiterados intentos de casar <factor> en la regla de recuperación de errores:
41        <objrule: factor>    (<val=([+-]?\d+(?:\.\d*)?)>)
42                           | \( <MATCH=expr> \)
43                           | ([^-+(0-9]+) (?{
44                                            # is + and not * to avoid infinite recursion
45                                            warn "Error: expecting a number or a open parenthesis, found: '". substr($^N, 0, 10)."'\n";
46                                            $warnings++;
47                                            $errors++;
48                                        }) <MATCH=factor>
en este caso resulta imposible encontrar un factor. Se puede cambiar la conducta indicando un (* COMMIT) antes de la llamada a <MATCH=factor>:
 41       <objrule: factor>    (<val=([+-]?\d+(?:\.\d*)?)>)
 42                          | \( <MATCH=expr> \)
 43                          | ([^-+(0-9]+) (?{
 44                                           # is + and not * to avoid infinite recursion
 45                                           warn "Error: expecting a number or a open parenthesis, found: '". substr($^N, 0, 10)."'\n";
 46                                           $warnings++;
 47                                           $errors++;
 48                                       }) (*COMMIT) <MATCH=factor>

en este caso la conducta es abandonar en el caso de que no se pueda encontrar un <factor>:

pl@nereida:~/Lregexpgrammars/demo/calculator$ ./calculatorwitherrmanagement.pl
Parsing infix arithmetic expressions (CTRL-D to end in unix) 2*(3+#)
Error: expecting a number or a open parenthesis, found: '#)'
1 warning
1 error
Parsing infix arithmetic expressions (CTRL-D to end in unix) 2*3
postfix: 2 3 *
result: 6
Parsing infix arithmetic expressions (CTRL-D to end in unix) @
Error: expecting a number or a open parenthesis, found: '@'
1 warning
1 error
Parsing infix arithmetic expressions (CTRL-D to end in unix) Bye!


next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Mensajes de Warning Sup: Análisis Sintáctico con Regexp::Grammars Ant: Depuración de Regexps Err: Si hallas una errata ...
Casiano Rodríguez León
2012-05-22