zubug55
zubug55

Reputation: 729

Exception handling in parser implemented using Marpa::R2

I have implemented a parser using Marpa::R2. Code appears like below:

I have a large number of test cases in a .t file, which i run to test my parser. So, if any exception arises in any of the input expression, testing shouldn't stop in mid and it should give proper error message for the one which has given an error (using exception handling) and rest of the test cases should run.

I want to do exception handling in this parser. If any sort of exception arrises even while tokenizing the input expression, I want to show appropriate message to the user, saying the position, string etc or any more details to show where the error came. Please help.

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\")";

I want to do Proper error handling like :http://blogs.perl.org/users/jeffrey_kegler/2012/10/a-marpa-dsl-tutorial-error-reporting-made-easy.html

I dont know how to put all this stuff in place.

Upvotes: 4

Views: 221

Answers (1)

daxim
daxim

Reputation: 39158

Wrap the lines that can fail in an exception handler:

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

The full error message from Marpa will be in $_, it is a single long string with newlines in it. I chose to print it to STDOUT with warn, and the program continues to run. As you can see in an example error message below, it contains the position where the parsing failed:

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.

If you need to, you could reformat it so it looks better to the user.

Upvotes: 2

Related Questions