| Gedcom documentation | Contained in the Gedcom distribution. |
Gedcom::Grammar - a module to manipulate Gedcom grammars
Version 1.16 - 24th April 2009
use Gedcom::Grammar;
my $st = $grammar->structure("GEDCOM");
my @sgr = $grammar->item("DATE");
my @items = $grammar->valid_items;
my $min = $grammar->min;
my $max = $grammar->max;
my @items = $grammar->items;
A selection of subroutines to handle the grammar of a gedcom file.
Derived from Gedcom::Item.
Some of the more important hash members are:
The top of the grammar tree.
A reference to a hash mapping the names of all structures to the grammar objects.
my $st = $grammar->structure("GEDCOM");
Return the grammar item of the specified structure, if it exists, or undef.
my @sgr = $grammar->item("DATE");
Return a list of the possible grammar items of the specified sub-item, if it exists.
my $min = $grammar->min;
Return the minimum permissible number of $grammar items
my $max = $grammar->max;
Return the maximum permissible number of $grammar items
my @items = $grammar->items;
Return a list of tags of the grammar's sub-items
my @items = $grammar->valid_items;
Return a hash detailing all the valid sub-items of the grammar item. The key is the tag of the sub-item and the value is an array of hashes with three members:
grammar => the sub-item grammar min => the minimum permissible number of these sub-items max => the maximum permissible number of these sub-items
| Gedcom documentation | Contained in the Gedcom distribution. |
# Copyright 1998-2009, Paul Johnson (paul@pjcj.net) # This software is free. It is licensed under the same terms as Perl itself. # The latest version of this software should be available from my homepage: # http://www.pjcj.net # documentation at __END__ use strict; require 5.005; package Gedcom::Grammar; use Data::Dumper; use Gedcom::Item 1.16; use vars qw($VERSION @ISA); $VERSION = "1.16"; @ISA = qw( Gedcom::Item ); sub structure { my $self = shift; my ($struct) = @_; unless (exists $self->{top}{structures}) { $self->{top}{structures} = { map { $_->{structure} ? ($_->{structure} => $_) : () } @{$self->{top}{items}} }; } # print Dumper $self->{top}{structures}; $self->{top}{structures}{$struct} } sub item { my $self = shift; my ($tag) = @_; return unless defined $tag; my $valid_items = $self->valid_items; # use Data::Dumper; print "[$tag] -- ", Dumper($self), Dumper $valid_items; return unless exists $valid_items->{$tag}; map { $_->{grammar} } @{$valid_items->{$tag}} } sub min { my $self = shift; exists $self->{min} ? $self->{min} : 1 } sub max { my $self = shift; exists $self->{max} ? $self->{max} eq "M" ? 0 : $self->{max} : 1 } sub items { my $self = shift; keys %{$self->valid_items} } sub _valid_items { my $self = shift; my %valid_items; for my $item (@{$self->{items}}) { my $min = $item->min; my $max = $item->max; if ($item->{tag}) { push @{$valid_items{$item->{tag}}}, { grammar => $item, min => $min, max => $max }; } else { die "What's a " . Data::Dumper->new([$item], ["grammar"]) unless my ($value) = $item->{value} =~ /<<(.*)>>/; die "Can't find $value in gedcom structures" unless my $structure = $self->structure($value); $item->{structure} = $structure; while (my($tag, $g) = each %{$structure->valid_items}) { push @{$valid_items{$tag}}, map { grammar => $_->{grammar}, # min and max can be calculated by multiplication because # the grammar always permits multiple selection records, and # selection records never have compulsory records. This may # change in future grammars, but I would not expect it to - # such a grammar would seem to have little practical use. min => $_->{min} * $min, max => $_->{max} * $max }, @$g; } if (exists $item->{items} && @{$item->{items}}) { my $extra_items = $item->_valid_items; while (my ($sub_item, $sub_grammars) = each %valid_items) { for my $sub_grammar (@$sub_grammars) { $sub_grammar->{grammar}->valid_items; while (my ($i, $g) = each %$extra_items) { # print "adding $i to $sub_item\n"; $sub_grammar->{grammar}{_valid_items}{$i} = $g; } } # print "giving @{[keys %{$sub_grammar->{grammar}->valid_items}]}\n"; } } } } # print "valid items are @{[keys %valid_items]}\n"; \%valid_items } sub valid_items { my $self = shift; $self->{_valid_items} ||= $self->_valid_items } 1; __END__