Re: Parsing binary AND/OR expressions, with brackets
[email protected] ("Ron D. Smith") Mon, 17 May 2004 16:35:33 -0700
| Newsgroups | perl.recdescent |
|---|---|
| Message-ID | <[email protected]> |
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