File Coverage

blib/lib/Gedcom/Grammar.pm
Criterion Covered Total %
statement 58 61 95.0
branch 16 22 72.7
condition 4 6 66.6
subroutine 10 11 90.9
pod 5 6 83.3
total 93 106 87.7


line stmt bran cond sub pod time code
1             # Copyright 1998-2013, Paul Johnson (paul@pjcj.net)
2              
3             # This software is free. It is licensed under the same terms as Perl itself.
4              
5             # The latest version of this software should be available from my homepage:
6             # http://www.pjcj.net
7              
8             # documentation at __END__
9              
10 11     11   37 use strict;
  11         11  
  11         394  
11              
12             require 5.005;
13              
14             package Gedcom::Grammar;
15              
16 11     11   35 use Data::Dumper;
  11         10  
  11         490  
17              
18 11     11   4591 use Gedcom::Item 1.20;
  11         165  
  11         280  
19              
20 11     11   47 use vars qw($VERSION @ISA);
  11         11  
  11         5629  
21             $VERSION = "1.20";
22             @ISA = qw( Gedcom::Item );
23              
24             sub structure {
25 519     519 0 410 my $self = shift;
26 519         436 my ($struct) = @_;
27 519 100       813 unless (exists $self->{top}{structures}) {
28             $self->{top}{structures} = {
29 232 50       440 map { $_->{structure} ? ($_->{structure} => $_) : () }
30 8         15 @{$self->{top}{items}}
  8         25  
31             };
32             }
33             # print Dumper $self->{top}{structures};
34 519         1220 $self->{top}{structures}{$struct}
35             }
36              
37             sub item {
38 6682     6682 1 4598 my $self = shift;
39 6682         4792 my ($tag) = @_;
40 6682 50       8114 return unless defined $tag;
41 6682         6629 my $valid_items = $self->valid_items;
42             # use Data::Dumper; print "[$tag] -- ", Dumper($self), Dumper $valid_items;
43 6682 100       9296 return unless exists $valid_items->{$tag};
44 6677         4170 map { $_->{grammar} } @{$valid_items->{$tag}}
  6696         12147  
  6677         7202  
45             }
46              
47             sub min {
48 1757     1757 1 1131 my $self = shift;
49 1757 50       2681 exists $self->{min} ? $self->{min} : 1
50             }
51              
52             sub max {
53 1757     1757 1 1070 my $self = shift;
54 1757 100       3515 exists $self->{max} ? $self->{max} eq "M" ? 0 : $self->{max} : 1
    50          
55             }
56              
57             sub items {
58 0     0 1 0 my $self = shift;
59 0         0 keys %{$self->valid_items}
  0         0  
60             }
61              
62             sub _valid_items {
63 595     595   434 my $self = shift;
64 595         375 my %valid_items;
65 595         460 for my $item (@{$self->{items}}) {
  595         920  
66 1757         1892 my $min = $item->min;
67 1757         1667 my $max = $item->max;
68 1757 100       2285 if ($item->{tag}) {
69 1247         710 push @{$valid_items{$item->{tag}}}, {
  1247         3667  
70             grammar => $item,
71             min => $min,
72             max => $max
73             };
74             } else {
75             die "What's a " . Data::Dumper->new([$item], ["grammar"])
76 510 50       2060 unless my ($value) = $item->{value} =~ /<<(.*)>>/;
77 510 50       708 die "Can't find $value in gedcom structures"
78             unless my $structure = $self->structure($value);
79 510         529 $item->{structure} = $structure;
80 510         400 while (my($tag, $g) = each %{$structure->valid_items}) {
  2667         2687  
81 2157         7163 push @{$valid_items{$tag}}, map {
82             grammar => $_->{grammar},
83             # min and max can be calculated by multiplication because
84             # the grammar always permits multiple selection records, and
85             # selection records never have compulsory records. This may
86             # change in future grammars, but I would not expect it to -
87             # such a grammar would seem to have little practical use.
88             min => $_->{min} * $min,
89 2157         1304 max => $_->{max} * $max
90             }, @$g;
91             }
92 510 100 66     821 if (exists $item->{items} && @{$item->{items}}) {
  510         1416  
93 8         22 my $extra_items = $item->_valid_items;
94 8         40 while (my ($sub_item, $sub_grammars) = each %valid_items) {
95 88         100 for my $sub_grammar (@$sub_grammars) {
96 88         128 $sub_grammar->{grammar}->valid_items;
97 88         176 while (my ($i, $g) = each %$extra_items) {
98             # print "adding $i to $sub_item\n";
99 176         480 $sub_grammar->{grammar}{_valid_items}{$i} = $g;
100             }
101             }
102             # print "giving @{[keys %{$sub_grammar->{grammar}->valid_items}]}\n";
103             }
104             }
105             }
106             }
107             # print "valid items are @{[keys %valid_items]}\n";
108 595         1580 \%valid_items
109             }
110              
111             sub valid_items {
112 62926     62926 1 42421 my $self = shift;
113 62926   66     112411 $self->{_valid_items} ||= $self->_valid_items
114             }
115              
116             1;
117              
118             __END__