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
key1val2
#endif
#if ! ( (defined ( val3 ) ) || ( defined (val4) ) )
key2val5
#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