I am using the simple boolean expression grammar below to learn how to use Marpa::R2. I am trying to understand how the Marpa loosen operator works.
#!/usr/bin/perl
use lib qw(/opt/share/perl/lib/perl5');
use strict;
use warnings;
use Marpa::R2;
my $BOOLEAN_EXPRESSION_DSL = q(
:default ::= action => eval
lexeme default = latm => 1
<boolean expression> ::=
<bit>
| ('(') <boolean expression> (')') action => ::first
| ('!') <boolean expression> action => not
| <boolean expression> '&&' <boolean expression> assoc => left action => and
|| <boolean expression> '||' <boolean expression> assoc => left action => or
<bit> ~ [01]
<blank> ~ [\s]+
:discard ~ <blank>
);
my $BOOLEAN_EXPRESSION_GRAMMAR = Marpa::R2::Scanless::G->new({source => \$BOOLEAN_EXPRESSION_DSL});
sub parse
{
my $e = shift;
my $recce = Marpa::R2::Scanless::R->new({grammar => $BOOLEAN_EXPRESSION_GRAMMAR, semantics_package => 'BOOLEAN_EXPRESSION_ACTIONS'});
my $length_read = $recce->read(\$e);
($length_read != length $e) and die("!!!ERROR: Syntax error in boolean expression [$e:$length_read].\n");
my $ambiguous_status = $recce->ambiguous();
($ambiguous_status) and die("!!!ERROR: Parse is ambiguous:\n$ambiguous_status");
my $ret = $recce->value;
print $$ret . "\n";
}
parse("0 && (1 || 1)");
sub BOOLEAN_EXPRESSION_ACTIONS::not
{
my (undef, $b) = @_;
return $b != 0 ? 0 : 1;
}
sub BOOLEAN_EXPRESSION_ACTIONS::and
{
my (undef, $lhs, undef, $rhs) = @_;
return ($lhs != 0 and $rhs != 0) ? 1 : 0;
}
sub BOOLEAN_EXPRESSION_ACTIONS::eval
{
my (undef, $v) = @_;
return (defined $v and $v != 0) ? 1 : 0;
}
When I run the program above I get this error:
Error in SLIF parse: No lexeme found at line 1, column 9
* String before error: 0 && (1\s
* The error was at line 1, column 9, and at character 0x007c '|', ...
* here: || 1)
Marpa::R2 exception at ./
test.pl line 29.
If I change my grammar and replace the loosen operator with the alternation operator, then it works! Why?
I am trying to use '||' to make the grammar unambiguous, so that I can drop the parenthesis, and be able to write 0 && 1 || 1.
Thank you!