Re: Parsing binary AND/OR expressions, with brackets

2004-05-18 Thread Ted Zlatanov
Look at cfperl:

ftp://ftp.lifelogs.com/pub/cfperl-latest.tar.gz

it has a separate P::RD grammar (there are several grammars for
distinct purposes) that analyzes cfengine-style conjunctions and
disjunctions; it should be pretty easy to adapt that to your needs.
It actually produces an expression tree that can be evaluated later,
since the value can change depending on the content of each term.
So that may be useful for you as well.

Ted


Re: Parsing binary AND/OR expressions, with brackets

2004-05-17 Thread Ron D. Smith
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