Re: :RD and OOP

[email protected] (Charly) Tue, 03 Aug 2004 23:34:28 +0200
Newsgroups perl.recdescent
Message-ID <[email protected]>
Alexander Farber wrote:
> Just to rephrase my question.
> 
> From my grammar I can save the parsed out data into global variables,
> like $::subdirs or $MyModule::subdirs. That works fine.
> 
> But how can I do it in OO-way, i.e. save data to $obj1->{subdirs} and then 
> parse another input text by the same parser and save it to $obj2->{subdirs}  ?

see my complete OO Style example. Hope this helps.
Anyway, your grammar looks a little bit odd, don't know
what your "component" will be.

Anyway, the OO trick with P::RD  is:

No logic in the grammar, all actions just call a $thisparser->method.
Collect the data under $thisparser->{local}...
and much more tricks in Config::Scoped.

Someone should write tis in the FAQ (a native speaker :-)
but it seems there is currently no FAQ P::RD::maintainer?

Happy parsing

	Charly
-- 
Karl Gaissmaier       KIZ/Infrastructure, University of Ulm, Germany
Email:[email protected]           Service Group Network



#!/usr/bin/perl

#########################################################
# MAIN
#########################################################

use warnings;
use strict;
use Data::Dumper;

#$::RD_HINT = 1;
#$::RD_TRACE = 20;

my $text = join '', <>;
my $parser = Nokia::Gen->new;
$parser->parse($text);

print Dumper( $parser->{local} );
exit 0;

#########################################################
# PARSER PACKAGE
#########################################################

package Nokia::Gen;

use warnings;
use strict;
use base 'Parse::RecDescent';

#
# PUT NO LOGIC INTO GRAMMARs!
# just use method calls, easy to debug and and and ...
#
use constant GRAMMAR => <<'EOGRAMMAR';

genfile: chunk(s) /^\Z/

chunk: comment | option | component | <error>

comment: /#.*$/
     {
       $thisparser->_comment( $item{__PATTERN1__} );
     }

# hmm, optarg(?) or optarg(s), anyway see the OO style
option: /<OPTION\b/i /\w+/ optarg(s) '>'
     {
       $thisparser->_option( $item{__PATTERN2__}, $item{'optarg(s)'} );
     }

optarg: /\w+/

# this rule seems to me very suspect, anyway just see the OO style
component: /\S+/ <skip: '[ \t]+'> dir
     {
       $thisparser->_component( $item{dir} );
     }

# seems to be very greedy, anyway it's your grammar ;-)
dir: /"[^"]*"/ | /\S+/

EOGRAMMAR

#####################################################
# constructor und parse method
#

sub new {
     my $class      = shift;
     my $thisparser = $class->SUPER::new(GRAMMAR);

     # set your local parameters
     $thisparser->{local}{comments}    = [];
     $thisparser->{local}{options}     = {};
     $thisparser->{local}{directories} = {};
     return $thisparser;
}

#####################################################
# public object methods
#

sub parse {
     my ( $thisparser, $text ) = @_;
     return $thisparser->genfile($text);
}

#####################################################
# private methods = ACTIONs
#

sub _comment {
     my ( $thisparser, $comment ) = @_;
     push @{ $thisparser->{local}{comments} }, $comment;
     return 1;    # rule success
}

sub _option {
     my ( $thisparser, $option_name, $option_list ) = @_;
     $option_name = lc $option_name;
     $thisparser->{local}{options}{$option_name} = $option_list;
     return 1;    # rule success
}

sub _component {
     my ( $thisparser, $dir ) = @_;
     $dir =~ s|\\\\+|/|g;
     warn "Warning: directory $dir not found\n"
       unless -d $dir;

     warn "Warning: directory $dir listed multiple times\n"
       if $thisparser->{local}{directories}{ uc $dir }++;

     return 1;    # rule success
}

1;               # keep require happy