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   62 use strict;
  11         21  
  11         446  
11              
12             require 5.005;
13              
14             package Gedcom::Grammar;
15              
16 11     11   56 use Data::Dumper;
  11         21  
  11         525  
17              
18 11     11   3957 use Gedcom::Item 1.20;
  11         170  
  11         268  
19              
20 11     11   53 use vars qw($VERSION @ISA);
  11         17  
  11         5479  
21             $VERSION = "1.20";
22             @ISA = qw( Gedcom::Item );
23              
24             sub structure {
25 519     519 0 640 my $self = shift;
26 519         735 my ($struct) = @_;
27 519 100       958 unless (exists $self->{top}{structures}) {
28             $self->{top}{structures} = {
29 232 50       567 map { $_->{structure} ? ($_->{structure} => $_) : () }
30 8         18 @{$self->{top}{items}}
  8         30  
31             };
32             }
33             # print Dumper $self->{top}{structures};
34 519         1351 $self->{top}{structures}{$struct}
35             }
36              
37             sub item {
38 6682     6682 1 7659 my $self = shift;
39 6682         8722 my ($tag) = @_;
40 6682 50       9832 return unless defined $tag;
41 6682         9012 my $valid_items = $self->valid_items;
42             # use Data::Dumper; print "[$tag] -- ", Dumper($self), Dumper $valid_items;
43 6682 100       11282 return unless exists $valid_items->{$tag};
44 6677         7065 map { $_->{grammar} } @{$valid_items->{$tag}}
  6696         15679  
  6677         10178  
45             }
46              
47             sub min {
48 1757     1757 1 1859 my $self = shift;
49 1757 50       3286 exists $self->{min} ? $self->{min} : 1
50             }
51              
52             sub max {
53 1757     1757 1 1865 my $self = shift;
54 1757 100       4333 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   735 my $self = shift;
64 595         639 my %valid_items;
65 595         639 for my $item (@{$self->{items}}) {
  595         1023  
66 1757         2878 my $min = $item->min;
67 1757         2434 my $max = $item->max;
68 1757 100       2724 if ($item->{tag}) {
69 1247         1295 push @{$valid_items{$item->{tag}}}, {
  1247         4455  
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       2361 unless my ($value) = $item->{value} =~ /<<(.*)>>/;
77 510 50       954 die "Can't find $value in gedcom structures"
78             unless my $structure = $self->structure($value);
79 510         711 $item->{structure} = $structure;
80 510         586 while (my($tag, $g) = each %{$structure->valid_items}) {
  2667         4358  
81 2157         8532 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         2436 max => $_->{max} * $max
90             }, @$g;
91             }
92 510 100 66     1017 if (exists $item->{items} && @{$item->{items}}) {
  510         1366  
93 8         28 my $extra_items = $item->_valid_items;
94 8         40 while (my ($sub_item, $sub_grammars) = each %valid_items) {
95 88         148 for my $sub_grammar (@$sub_grammars) {
96 88         161 $sub_grammar->{grammar}->valid_items;
97 88         209 while (my ($i, $g) = each %$extra_items) {
98             # print "adding $i to $sub_item\n";
99 176         532 $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         1890 \%valid_items
109             }
110              
111             sub valid_items {
112 62926     62926 1 70331 my $self = shift;
113 62926   66     122964 $self->{_valid_items} ||= $self->_valid_items
114             }
115              
116             1;
117              
118             __END__