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 > >