Ok. I should have read your original post in detail... Sorry. :-)
Anyway, a couple of quick thoughts then a chunk of code and im off for the
weekend.
First :Try using here docs instead of q{}. They make your grammer much
cleaner. (and avoid potential issues with \ which i suspect you may be
suffering).
Second:I wonder if using reserved words as rule names is part of the
weirdness you describe.
Third :> atom: /(\w+)/ { $return = ::get_value($1); 1; }
This is better written (IMO) as
> atom: /\w+/ { $return = ::get_value($item[1]);}
K, heres a quick little parser I whipped together that does what you had in
mind.
Maybe you can use it to resolve your issues. (Its not fully tested, and I
had to make up a few things since I didnt have the full rules of your
grammer handy)
The output is after the __END__ tag.
hth. Yves
use Parse::RecDescent;
use warnings;
use strict;
my %symbols;
sub symbol_fetch{
my $symbol=shift;
unless (exists $symbols{$symbol}) {
warn "Fetching from nonexiststant $symbol\n";
$symbols{$symbol}=0;
}
print "Fetched $symbol=$symbols{$symbol}\n";
return $symbols{$symbol}
}
sub symbol_store{
my $symbol=shift;
my $value =shift;
$symbols{$symbol}=$value;
print "Stored $value into $symbol\n";
return $value
}
my $grammar=<<'GRAMMAR';
statements : statement(s) /\Z/
| <error>
statement : conj_atom '::' action[$item{conj_atom}]
| <error>
action : {print "\$arg[0] is ".($arg[0]?"True":"False")."\n"; undef}
| 'define' '(' symbol ')' { $arg[0] &&
::symbol_store($item{symbol},1); 1}
| 'undefine' '(' symbol ')' { $arg[0] &&
::symbol_store($item{symbol},0); 1}
| 'print' '(' /[^)]+/ ')' { $arg[0] && print $item[3],"\n"; 1}
conj_atom : conj {$return=$item{conj}}
| atom {$return=$item{atom}}
conj :<leftop: disj_atom '.' disj_atom>
{ $return=1;
foreach my $item (@{$item[1]}) {
$return&&=$item;
last if !$return;
}
$return
}
disj_atom : disj {$return=$item{disj}}
| atom {$return=$item{atom}}
disj :<leftop: atom '|' atom>
{ $return=0;
foreach my $item (@{$item[1]}) {
$return||=$item;
last if $return;
}
$return
}
atom : '!' atom {$return=!$item{atom} }
| '(' conj_atom ')' {$return=$item{conj_atom}}
| symbol {$return=::symbol_fetch($item{symbol})}
symbol : /\w+/ { $return=$item[1]; }
GRAMMAR
#$::RD_HINT=1;
#$::RD_TRACE=1;
my $parser=Parse::RecDescent->new($grammar) or die "Bad grammar!\n";
defined $parser->statements(<<TEST) or die "Cant parse!"
!a :: define(a)
a|b|c :: define(hello)
a.b.hello:: print(hello is defined)
a :: print(a is defined)
!c :: define(c)
c.(a|b) :: print(c and a or b)
TEST
__END__
Fetching from nonexiststant a
Fetching from nonexiststant b
Fetching from nonexiststant c
Fetched a=0
$arg[0] is True
Stored 1 into a
Fetched a=1
Fetched b=0
Fetched c=0
$arg[0] is True
Stored 1 into hello
Fetched a=1
Fetched b=0
Fetched hello=1
$arg[0] is False
Fetched a=1
$arg[0] is True
a is defined
Fetched c=0
$arg[0] is True
Stored 1 into c
Fetched c=1
Fetched a=1
Fetched b=0
$arg[0] is True
c and a or b
> -----Original Message-----
> From: Ted Zlatanov [mailto:[EMAIL PROTECTED]]
> Sent: 2002/03/14 21:09
> To: Orton, Yves
> Cc: [EMAIL PROTECTED]
> Subject: Re: evaluating parsed expressions
>
>
> Thanks for the suggestions. I don't want to keep a symbol table,
> because it would have to be cleared every time I re-run the parser.
> The state of the defined classes (and thus the logical value of each
> symbol) may change with each invocation of the parser (once per
> configuration line). I'm not parsing a static file, each line may
> actually define a new class or undefine an old one. Something like
> this (define/undefine syntax is not important):
>
> # start with a,c,d defined
> a.c.d:: define(hello) # will run
> a.c.hello:: undefine(a) # will run
> a:: anything() # will not run
>
> A simplified version of my unsuccessful grammars:
>
> or: atom '|' atom { $return = $item[1] || $item[3]; 1; }
> atom: /(\w+)/ { $return = ::get_value($1); 1; }
>
> did not work for me. The parser would always break off at the 'or'
> without descending into the atom evaluation, or I would get weird
> parsing errors. I ended up having each parsed element return a
> subroutine that, when evaluated with the matched parameters, will do
> the right thing. See my previous message for the gory details.
>
> I hope my explanations are making this clearer. I keep having the
> feeling the answer is very simple, I just don't get it :)
>
> Thanks
> Ted
>
>