1) you needed to fix the syntax error. (It was the 'i' modifier on the (s/&&/i) 2) you did not define nested parentheses as the highest priority and allow for any number of them 3) the <skip> was *demanding* to be there ('+' instead of '*')
The following produces output but I'm still not sure what you are doing... use strict; use vars qw($parser $text %top); use Data::Dumper; use Parse::RecDescent; $RD_WARN = 1; $RD_HINT = 1; $RD_TRACE = 120; $parser = Parse::RecDescent->new(q( mmpfile: chunk(s) /^\Z/ chunk: assignment | ifdef|<error> assignment: keyword <skip: '[ \t]*'> value(s) { push @{$::top{uc $item{keyword}}}, @{$item[-1]}; } ifdef: /#\s*if/ <skip: '[ \t]*'> conjunction <skip: $item[2]> chunk(s?) /#\s*endif/ conjunction: disjunction(s /&&/) disjunction: unary_expr(s /\|\|/) unary_expr: '!' defined_expr | defined_expr defined_expr: 'defined' '(' value ')' | 'defined' value | '(' conjunction ')' value: /VAL\d+\b/i keyword: /KEY\d+\b/i )) or die 'Bad grammar'; $text .= $_ while (<DATA>); defined $parser->mmpfile($text) or die 'Bad text'; print Data::Dumper->Dump([\%top], [qw(top)]); __DATA__ #if defined val1 key1 val2 #endif #if ! ( (defined ( val3 ) ) || ( defined (val4) ) ) key2 val5 #endif On Monday, May 17, 2004 Alexander Farber said: > Hi, > > could someone please help me few steps further? > I'm almost finished with the parser I need. > > The only missing part is grokking C-preprocessor-like > #if defined / #endif expressions, which can be surrounded > by brackets and contain && and || as binary operators. > > Unfortunately my script fails already with > some syntax error, which I couldn't fix yet: > > Parse::RecDescent: Treating "conjunction:" as a rule declaration > > Warning: Undefined (sub)rule "keyword" used in a production. > (Hint: Will you be providing this rule later, or did you > perhaps misspell "keyword"? Otherwise it will be > treated as an immediate <reject>.) > > Warning: Undefined (sub)rule "value" used in a production. > (Hint: Will you be providing this rule later, or did you > perhaps misspell "value"? Otherwise it will be treated > as an immediate <reject>.) > > Also, please any suggestions on how to handle the > nested brackets properly? I keep looking at the > demo_operator.pl and other P::RD examples but couldn't > figure it out yet... > > What I also don't know yet, is in which datastructure > to save the binary operators and conditions that I'm > trying to parse. I'm trying to convert the format below > to the GNU make's ifdef/ifndef > > Regards > Alex > > > #!/usr/bin/perl -w > > use strict; > use vars qw($parser $text %top); > use Data::Dumper; > use Parse::RecDescent; > $RD_WARN = 1; > $RD_HINT = 1; > $RD_TRACE = 120; > $parser = Parse::RecDescent->new(q( > > mmpfile: chunk(s) /^\Z/ > chunk: assignment | <error> > > assignment: keyword <skip: '[ \t]+'> value(s) { > push @{$::top{uc $item{keyword}}}, @{$item[-1]}; > } > > ifdef: /#\s*if/ <skip: '[ \t]+'> condition > <skip: $item[2]> chunk(s?) > /#\s*endif/ > > condition: '(' conjunction ')' | conjunction > conjunction: disjunction(s /&&/i) > disjunction: unary_expr(s /\|\|/i) > unary_expr: '!' defined_expr | defined_expr > defined_expr: 'defined' '(' value ')' | 'defined' value > > value: /VAL\d+\b/i > keyword: /KEY\d+\b/i > > )) or die 'Bad grammar'; > $text .= $_ while (<DATA>); > defined $parser->mmpfile($text) or die 'Bad text'; > print Data::Dumper->Dump([\%top], [qw(top)]); > > __DATA__ > #if defined val1 > key1 val2 > #endif > > #if ! ( (defined ( val3 ) ) || ( defined (val4) ) ) > key2 val5 > #endif -- Intel, Corp. 5000 W. Chandler Blvd. Chandler, AZ 85226 -- Intel, Corp. 5000 W. Chandler Blvd. Chandler, AZ 85226