use strict; my $ParseErrorFh; BEGIN { open(my $olderr, '>&STDERR') or die "Cannot dup STDERR: $!"; close STDERR or die "Cannot close STDERR: $!"; open(STDERR, '+>', undef) or die "Cannot open anonymous file: $!"; select STDERR; $| = 1; open($ParseErrorFh, '>&STDERR') or die "Cannot dup anonymous file: $!"; require Parse::RecDescent; close STDERR or die "Cannot close STDERR: $!"; open(STDERR, '>&', $olderr) or die "Cannot restore STDERR: $!"; } sub parse { my ($grammar, $str) = @_; local $::RD_ERROR = 1; local $::RD_WARN = 2; seek($ParseErrorFh, 0, 0); my $p = Parse::RecDescent->new($grammar) or die "Grammar is invalid"; my $x = $p->start($str); if (not defined $x) { seek($ParseErrorFh, 0, 0); die join '', grep { $_ !~ m/^\s*$/ } <$ParseErrorFh>; } return $x; } print parse('start: /foo/ | ', 'fo'), "\n"; #### $ perl rectest.pl ERROR (line 1): Invalid start: Was expecting /foo/ #### $ perl rectest2.pl ERROR (line 1): Invalid start: Was expecting /foo/ Died at recdescent.pl line 34. #### use strict; use Parse::RecDescent; sub parse { my ($grammar, $str) = @_; open(local *Parse::RecDescent::ERROR, '>', \my $error) or die "Cannot open in-memory filehandle: $!"; local $::RD_ERROR = 1; local $::RD_WARN = 2; my $p = Parse::RecDescent->new($grammar) or die "Grammar is invalid"; my $x = $p->start($str); defined $x or die $error; return $x; } print parse('start: /foo/ | ', 'fo'), "\n"; #### $ perl recdescent3.pl Undefined format "Parse::RecDescent::ERROR" called at /usr/share/perl5/Parse/RecDescent.pm line 2910.