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


Reply via email to