I agree with Dave that
Parse::RecDescent could be a good way to do it. If you want to "roll your own" though, you could do something like:
#!/usr/bin/perl -w
use strict;
package Item;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless ($self, $class);
return $self;
}
sub add_attribute {
my $self = shift;
my ($key,$value) = @_;
$self->{$key} = $value;
}
1; #included in case Item becomes a real Module someday.
package Section;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{Items} = [];
bless ($self, $class);
return $self;
}
sub add_attribute {
my $self = shift;
my ($key,$value) = @_;
$self->{$key} = $value;
}
sub add_item {
my $self = shift;
my $item = Item->new();
push @{$self->{Items}},$item;
return $item;
}
1; #Ditto
package UberObject;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = [];
bless ($self, $class);
return $self;
}
sub add_section {
my $self = shift;
my $section = Section->new();
push @$self,$section;
return $section;
}
1; #again
package Main;
use Data::Dumper;
my $uo = new UberObject();
my ($section,$item) = (undef,undef);
while (<>) { #dammit Jim, parse the data already!
if (/begin_section/) {
$section = $uo->add_section();
} elsif (/end_section/) {
undef $section;
} elsif (/begin_item/) {
$item = $section->add_item();
} elsif (/end_item/) {
undef $item;
} elsif (/=/) {
if (defined($item)) {
$item->add_attribute(split(/=/));
} elsif (defined($section)) {
$section->add_attribute(split(/=/));
} else {
die "Bad attribute at line $.";
}
}
}
#probably should do something interesting .....
# .... nah Just Dump it all!
my $d=Data::Dumper->new([$uo],['UberObject']);
$d->Indent(1);
print $d->Dump();
When tested with a file that contains:
begin_section
name=section1
type=section_type1
begin_item
name=item1
desc=item_description1
link=item_link1
end_item
begin_item
name=item2
desc=item_description2
link=item_link2
end_item
end_section
begin_section
name=section2
type=section_type2
begin_item
name=item21
desc=item_description21
link=item_link21
end_item
begin_item
name=item22
desc=item_description22
link=item_link22
end_item
end_section
yields:
"The correct thing" (Exercise left to reader)
You may also consider massaging the data (or writing a converter) to XML and use
XML::Parser which can also be used in an OOish way..
Note: As the last poster mentioned while I was busy typing, Error checking = Good, and I don't do enough of it in my example... another excersize left to reader.
Hope that helps,
-
ase