#! /usr/local/bin/perl -sw
sub
trace_only {
my
(
$pattern
) =
@_
;
$RD_TRACE
=1;
my
$_real_trace
= \
&Parse::RecDescent::_trace
;
*Parse::RecDescent::_trace
=
sub
($;$$$) {
my
(
$msg
,
$context
,
$rulename
,
$level
) =
@_
;
return
if
$msg
!~
$pattern
;
goto
&{
$_real_trace
};
};
}
my
$parse
= Parse::RecDescent->new(
<<'EOG');
<autotree: LOGICAL>
expr : set | clear | disj
set : 'set' atom
clear : 'clear' atom
disj : <leftop: conj 'or' conj>
{ bless $item[-1], 'LOGICAL::'.$item[0] }
conj : <leftop: unary 'and' unary>
{ bless $item[-1], 'LOGICAL::'.$item[0] }
unary : neg | bracket | atom
bracket : '(' expr ')'
neg : 'not' unary
atom : /[a-z]+/i
EOG
trace_only(
qr/Matched|consumed/
);
while
(<DATA>)
{
my
$tree
=
$parse
->expr(
$_
);
print
Data::Dumper->Dump([
$tree
]);
print
$tree
->
eval
(),
"\n"
if
$tree
;
}
BEGIN {
@var
{
qw(a c e)
} = (1,1,1);}
sub
returning
{
$_
[0];
}
sub
LOGICAL::expr::
eval
{
my
$type
=
$_
[0]->{set}||
$_
[0]->{clear}
||
$_
[0]->{disj};
returning
$type
->
eval
() }
sub
LOGICAL::disj::
eval
{ returning
join
''
,
map
{
$_
->
eval
()} @{
$_
[0]} }
sub
LOGICAL::conj::
eval
{ returning !
join
''
,
map
{!
$_
->
eval
()} @{
$_
[0]} }
sub
LOGICAL::unary::
eval
{
my
$type
=
$_
[0]->{neg}||
$_
[0]->{bracket}
||
$_
[0]->{atom};
returning
$type
->
eval
() }
sub
LOGICAL::bracket::
eval
{ returning
$_
[0]->{expr}->
eval
() }
sub
LOGICAL::neg::
eval
{ returning !
$_
[0]->{unary}->
eval
() }
sub
LOGICAL::set::
eval
{ returning $::var{
$_
[0]->{atom}->name()} = 1 }
sub
LOGICAL::clear::
eval
{ returning $::var{
$_
[0]->{atom}->name()} = 0 }
sub
LOGICAL::atom::
eval
{ returning $::var{
$_
[0]->{__VALUE__}} }
sub
LOGICAL::atom::name { returning
$_
[0]->{__VALUE__} }