use strict;
use warnings;
use Marpa::R2;
package DoStuff;
my %vars;
sub doAnd {
my @params = @_;
return $params[1] && $params[3];
}
sub doOr {
my @params = @_;
return $params[1] || $params[3];
}
sub doVarValue {
my @params = @_;
return $vars{$params[1]};
}
sub doAssign {
my @params = @_;
$vars{$params[1]} = $params[3];
return;
}
sub doVal {
my @params = @_;
my $val = 'ARRAY' eq ref $params[1] ? $params[1][1] : $params[1];
return $val;
}
sub doNVal {
my @params = @_;
my $val = 'ARRAY' eq ref $params[2] ? $params[2][1] : $params[2];
return $val ? 0 : 1;
}
sub doResult {
my @params = @_;
return $params[-1];
}
package main;
my $syntax = <<'SYNTAX';
lexeme default = latm => 1
test ::= assignments expression action => doResult
| expression action => doResult
assignments ::= assignment assignments
| assignment
assignment ::= var '=' constant action => doAssign
expression ::= expression '|' term action => doOr | term action => ::first
term ::= term '&' factor action => doAnd | factor action => ::first
factor ::= negatable action => doVal | '!' negatable action => doNVal
negatable ::= '(' expression ')' action => [values] | value action => ::first
value ::= var action => doVarValue
| constant action => ::first
var ~ [A-Z]
constant ~ [10]
:discard ~ spaces
spaces ~ [\s]+
SYNTAX
my $grammar = Marpa::R2::Scanless::G->new({source => \$syntax});
for my $inputs ([0, 0, 0], [0, 0, 1], [0, 1, 1], [1, 0, 1]) {
my $input = <[0]
Q = $inputs->[1]
T = $inputs->[2]
(!(C)&T)&!Q
INPUT
my $result = $grammar->parse(\$input, 'DoStuff');
printf "${input}Result: %d\n\n", $$result;
}
####
C = 0
Q = 0
T = 0
(!(C)&T)&!Q
Result: 0
C = 0
Q = 0
T = 1
(!(C)&T)&!Q
Result: 1
C = 0
Q = 1
T = 1
(!(C)&T)&!Q
Result: 0
C = 1
Q = 0
T = 1
(!(C)&T)&!Q
Result: 0