4

我已经使用 Marpa::R2 实现了一个解析器。代码如下所示:

我在一个 .t 文件中有大量测试用例,我运行这些测试用例来测试我的解析器。因此,如果任何输入表达式中出现任何异常,测试不应该在中间停止,它应该为给出错误的那个(使用异常处理)提供正确的错误消息,并且其余的测试用例应该运行。

我想在这个解析器中进行异常处理。如果即使在对输入表达式进行标记时出现任何类型的异常,我想向用户显示适当的消息,说明位置、字符串等或任何更多详细信息以显示错误出现的位置。请帮忙。

use strict;
use Marpa::R2;
use Data::Dumper;

my $grammar = Marpa::R2::Scanless::G->new({
    default_action => '[values]',
    source => \(<<'END_OF_SOURCE'),
    lexeme default = latm => 1

:start ::= expression

expression ::= expression OP expression
expression ::= expression COMMA expression
expression ::= func LPAREN PARAM RPAREN
expression ::= PARAM
PARAM ::= STRING | REGEX_STRING
REGEX_STRING ::= '"' QUOTED_STRING '"'

:discard    ~ sp
sp          ~ [\s]+

COMMA                      ~ [,]
STRING                     ~ [^ \/\(\),&:\"~]+
QUOTED_STRING              ~ [^ ,&:\"~]+
OP                         ~ ' - ' | '&'
LPAREN                     ~ '('
RPAREN                     ~ ')'
func                       ~ 'func'

END_OF_SOURCE
});

my $recce = Marpa::R2::Scanless::R->new({grammar => $grammar});
print "Trying to parse:\n$input\n\n";
$recce->read(\$input);
my $value_ref = ${$recce->value};
print "Output:\n".Dumper($value_ref);

my $input4 = "func(\"foo\")";

我想做正确的错误处理,例如:http: //blogs.perl.org/users/jeffrey_kegler/2012/10/a-marpa-dsl-tutorial-error-reporting-made-easy.html

我不知道如何将所有这些东西放在适当的位置。

4

1 回答 1

2

在异常处理程序中包装可能失败的行:

use Try::Tiny;
⋮
try {
    $recce->read(\$input);
    my $value_ref = ${$recce->value};
    print "Output:\n".Dumper($value_ref);
} catch {
    warn $_;
};

来自 Marpa 的完整错误消息将在 中$_,它是一个带有换行符的长字符串。我选择用 将它打印到 STDOUT warn,程序继续运行。正如您在下面的示例错误消息中看到的那样,它包含解析失败的位置:

Error in SLIF parse: No lexeme found at line 1, column 5
* String before error: "fo\s
* The error was at line 1, column 5, and at character 0x006f 'o', ...
* here: o"
Marpa::R2 exception at so49932329.pl line 41.

如果需要,您可以重新格式化它,以便用户看起来更好。

于 2018-04-20T10:47:17.403 回答