All, I have an object that I create with a 'file' method. The 'file' method uses Parse::RecDescent to parse the file and store some of the contents into the object. I am having problems figuring out how to get parse::recdescent to store the data into my object, however.
My package is called Klarf::1_8 I have a rule in my grammer that looks like this:
list : LIST HEADER { Klarf::1_8::_store_list( $self, $item{HEADER} ) }
I have this subroutine:
sub _store_list{ my $self = shift; my $header = lc shift; my $ref = _get_hash_of_level(); $ref->{$header} = {}; $self->{_current_state} = 'LIST'; $self->{_current_list} = $header; say "Found $header" if $self->{_verbose}; }
The problem is that in my grammer, $self is in the namespace of the Parse::Recdescent object, so my sub gets the Parse::Recdesent object. I tried using Klarf::1_8::_store_list( $__PACKAGE__::self, $item{HEADER} ) but that doesn't work because I haven't declared a package variable by that name. Here is my file sub:
sub file { my $self = shift; my $file = shift; if ( not -f $file ){ carp 'Invalid filename provided' }; my @grammer = <DATA>; my $grammer = join ' ', @grammer; my $parser = Parse::RecDescent->new( $grammer ); open my $file_h, '<', $file or croak q{Couldn't open file}; while ( my $line = <$file_h> ){ chomp $line; $parser->startrule($line); } close $file_h; return $file; }
Is there anyway I can accomplish this? I am sure there is. Thanks, David Just in case, here is my complete code
package Klarf::1_8; use strict; use warnings; use Parse::RecDescent; use File::Slurp; use Carp; use Mouse; use feature ':5.10'; use Data::Dumper; =head3 verbose Turns on messages to see what is going on with the parser. =cut sub verbose { my $self = shift; my $verbose = shift; $self->{_verbose} = $verbose; return $verbose; } =head3 file Loads the file and parses it. Returns the filename upon success. =cut sub file { my $self = shift; my $file = shift; if ( not -f $file ){ carp 'Invalid filename provided' }; my @grammer = <DATA>; my $grammer = join ' ', @grammer; my $parser = Parse::RecDescent->new( $grammer ); open my $file_h, '<', $file or croak q{Couldn't open file}; while ( my $line = <$file_h> ){ chomp $line; $parser->startrule($line); } close $file_h; return $file; } sub _store_list{ my $self = shift; my $header = lc shift; my $ref = _get_hash_of_level(); $ref->{$header} = {}; $self->{_current_state} = 'LIST'; $self->{_current_list} = $header; say "Found $header" if $self->{_verbose}; } sub _store_data{ my $self = shift; $self->{_current_state} = 'DATA'; } sub _store_line{ my $self = shift; my $line = shift; my $col = shift; my $data_or_header = defined $col ? 'header' : $self->{_current_state} ne 'DATA' ? 'header' :'data'; my $ref = _get_hash_of_level(); push @{$ref->{$self->{_current_list}}->{$data_or_header}}, $line; } sub _store_field{ my $self = shift; my $header = lc shift; my $int = shift; my $array = shift; $array =~ s/[{}]//g; my @array = split /,/, $array; carp "Expecting field size $int in list $array. Field $header get +s undef." unless $int == scalar @array; foreach my $item ( @array ){ $item =~ s/["\s]//g; } my $storable; if ( $int == 1 ){ $storable = $array[0] } else { $storable = \@array }; my $ref = _get_hash_of_level(); $ref->{$header} = $storable; say "Found $header:\t$array" if $self->{_verbose}; } # i need to know which level of the hash to store each record. # so this sub returns the correct hash for later storage. sub _get_hash_of_level{ my $self = shift; my $idx = $self->{level}; $idx--; my @array = @{$self->{_headerlist}}; if ( not defined $idx ){ $idx = 0 }; my $level = $array[$idx]; given ( $level ){ when ( 'filerecord' ) { return $self } when ( 'lotrecord' ) { return $self } when ( 'waferrecord' ) { return $self->{$self->{_current_wafe +r}} } when ( 'testrecord' ) { return $self->{$self->{_current_wafe +r}}->{$self->{_current_test}} } when ( 'summaryrecord' ){ return $self->{$self->{_current_wafe +r}}} } } sub _store_record{ my $self = shift; my $header = lc shift; my $value = shift; $value //= ''; #/ print Dumper $self; die; chomp $header; chomp $value; $value =~ s/"//g; $self->{_current_record} = $header; # want to keep the header list so i can look it up via indexing... push @{$self->{_headerlist}}, $header unless grep { $header eq $_ } @{$self->{_headerlist}}; given ( $header ){ when ( 'lotrecord' ){ $self->{_current_lot} = $value; $self->{$header} = $value; } when ( 'waferrecord' ){ $self->{_current_wafer} = $value; $self->{_num_wafers}++; $self->{$value} = {}; } when ( 'testrecord' ){ $self->{_current_test} = $value; $self->{$self->{_current_wafer}}->{$self->{_current_test}} + = {}; } when ( 'filerecord' ){ $self->{$header} = $value; } when ( 'summaryrecord' ){ $self->{$self->{_current_wafer}}->{$header} = {}; } } say "Found $header:\t$value" if $self->{_verbose}; } # increments and decrements the 'level' of the objectc # by counting the brackets sub _level{ my $self = shift; my $dir = shift; if ( $dir eq '+' ){ $self->{_level}++; } elsif ( $dir eq '-' ){ $self->{_level}--; } } 1; # DATA filehandle holds the grammer for parsing the klarf. __DATA__ RECORD : /Record/i FIELD : /Field/i LIST : /List/i COLUMN : /Columns/i DATA : /Data/i HEADER : /[\s]*[A-Za-z]+/ VALUE : /[\s]*["]?[\w\.]+["]?/ INT : /\d+/ ARRAY : /\{.+\}/ LINE : /.+/ record : RECORD HEADER VALUE(?) { Klarf::1_8::_store_record( $__PACKAGE__::self, $item{HEADER}, +$item{'VALUE(?)'}->[0] ) } field : FIELD HEADER INT ARRAY { Klarf::1_8::_store_field( $self, $item{HEADER}, $item{INT}, $i +tem{ARRAY} ) } list : LIST HEADER { Klarf::1_8::_store_list( $self, $item{HEADER} ) } data : DATA INT { Klarf::1_8::_store_data( $self ) } column : COLUMN INT LINE { Klarf::1_8::_store_line( $self, $item{LINE}, 'col' ) } obracket : /{/ { Klarf::1_8::_level( $self, '+') } cbracket : /}/ { Klarf::1_8::_level( $self, '-') } line : LINE { Klarf::1_8::_store_line( $self, $item{LINE} ) } klarfline : record | field | list | data | column | obracket | + cbracket | line startrule : klarfline(s /;/)

In reply to Using Parse::RecDescent in an Object by ~~David~~

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.