File Coverage

blib/lib/DateTime/Format/Natural/Expand.pm
Criterion Covered Total %
statement 81 81 100.0
branch 15 16 93.7
condition 2 3 66.6
subroutine 7 7 100.0
pod n/a
total 105 107 98.1


line stmt bran cond sub pod time code
1             package DateTime::Format::Natural::Expand;
2              
3 26     26   235 use strict;
  26         58  
  26         1021  
4 26     26   158 use warnings;
  26         51  
  26         1582  
5 26     26   147 use boolean qw(true false);
  26         91  
  26         165  
6              
7 26     26   2172 use Clone qw(clone);
  26         95  
  26         1702  
8 26     26   14251 use DateTime::Format::Natural::Helpers qw(%flag);
  26         98  
  26         42795  
9              
10             our $VERSION = '0.04';
11              
12             my %data = (
13             time => {
14             4 => {},
15             5 => '_time',
16             6 => { truncate_to => [q(hour_minute_second)] },
17             },
18             time_min => {
19             4 => {},
20             5 => '_time',
21             6 => { truncate_to => [q(minute_second)] },
22             },
23             time_am => {
24             2 => 'meridiem',
25             3 => $flag{time_am},
26             4 => {},
27             5 => '_at',
28             6 => { truncate_to => [q(hour_minute_second)] },
29             },
30             time_pm => {
31             2 => 'meridiem',
32             3 => $flag{time_pm},
33             4 => {},
34             5 => '_at',
35             6 => { truncate_to => [q(hour_minute_second)] },
36             },
37             );
38              
39             my %expand_prefix = (
40             date_literal_variant => [ qw( time_min time_am time_pm) ],
41             week_variant => [ qw( time_min time_am time_pm) ],
42             month_variant => [ qw( time_min time_am time_pm) ],
43             year_variant => [ qw( time_min time_am time_pm) ],
44             weekday_variant_week => [ qw(time time_am time_pm) ],
45             variant_week_weekday => [ qw(time time_am time_pm) ],
46             final_weekday_in_month => [ qw(time time_am time_pm) ],
47             month_day => [ qw( time_min time_am time_pm) ],
48             day_month_variant_year => [ qw( time_min time_am time_pm) ],
49             day_month_year_ago => [ qw( time_min time_am time_pm) ],
50             count_weekday => [ qw( time_min time_am time_pm) ],
51             count_yearday => [ qw( time_min time_am time_pm) ],
52             count_weekday_from_now => [ qw( time_min time_am time_pm) ],
53             count_day_variant_week => [ qw( time_min time_am time_pm) ],
54             count_day_variant_month => [ qw( time_min time_am time_pm) ],
55             count_month_variant_year => [ qw( time_min time_am time_pm) ],
56             count_weekday_variant_month => [ qw( time_min time_am time_pm) ],
57             count_weekday_in_month => [ qw( time_min time_am time_pm) ],
58             count_yearday_variant_year => [ qw( time_min time_am time_pm) ],
59             );
60             my %expand_suffix = (
61             date_literal_variant => [ qw( time_min time_am time_pm) ],
62             week_variant => [ qw( time_min time_am time_pm) ],
63             month_variant => [ qw( time_min time_am time_pm) ],
64             year_variant => [ qw( time_min time_am time_pm) ],
65             weekday_variant_week => [ qw(time time_am time_pm) ],
66             variant_week_weekday => [ qw(time time_am time_pm) ],
67             final_weekday_in_month => [ qw(time time_am time_pm) ],
68             day_month_variant_year => [ qw( time_min time_am time_pm) ],
69             day_month_year_ago => [ qw( time_min time_am time_pm) ],
70             count_weekday => [ qw( time_min time_am time_pm) ],
71             count_yearday => [ qw( time_min time_am time_pm) ],
72             count_weekday_from_now => [ qw( time_min time_am time_pm) ],
73             count_day_variant_week => [ qw( time_min time_am time_pm) ],
74             count_day_variant_month => [ qw( time_min time_am time_pm) ],
75             count_month_variant_year => [ qw( time_min time_am time_pm) ],
76             count_weekday_variant_month => [ qw( time_min time_am time_pm) ],
77             count_weekday_in_month => [ qw( time_min time_am time_pm) ],
78             count_yearday_variant_year => [ qw( time_min time_am time_pm) ],
79             );
80              
81             my $save = sub
82             {
83             my ($type, $target, @values) = @_;
84              
85             if ($type eq 'prefix') {
86             unshift @$target, @values;
87             }
88             elsif ($type eq 'suffix') {
89             push @$target, @values;
90             }
91             };
92              
93             sub _expand_for
94             {
95 758380     758380   1239547 my $self = shift;
96 758380         1377344 my ($keyword) = @_;
97              
98 758380 100 66     2917022 return (exists $expand_prefix{$keyword} || exists $expand_suffix{$keyword}) ? true : false;
99             }
100              
101             sub _expand
102             {
103 24126     24126   240017 my $self = shift;
104 24126         74398 my ($keyword, $types_entry, $grammar) = @_;
105              
106 24126         109800 my %expand = (
107             prefix => \%expand_prefix,
108             suffix => \%expand_suffix,
109             );
110              
111 24126         52306 my (@expandable, @expansions);
112              
113 24126 50       122666 push @expandable, 'prefix' if exists $expand_prefix{$keyword};
114 24126 100       88643 push @expandable, 'suffix' if exists $expand_suffix{$keyword};
115              
116 24126         66575 foreach my $type (@expandable) {
117 45430         85728 my @elements = @{$expand{$type}->{$keyword}};
  45430         180886  
118              
119 45430         101896 foreach my $element (@elements) {
120 136290         302516 foreach my $entry (@$grammar) {
121 354930         2742517 my $types = clone($types_entry);
122              
123 354930         1101978 $save->($type, $types, 'REGEXP');
124              
125 354930         12358542 my $new = clone($entry);
126              
127 354930 100       1146945 if ($type eq 'prefix') {
128 185931         333560 my %definition;
129 185931         346722 while (my ($pos, $def) = each %{$new->[0]}) {
  654648         2082898  
130 468717         1396797 $definition{$pos + 1} = $def;
131             }
132 185931         435105 %{$new->[0]} = %definition;
  185931         670243  
133              
134 185931         403821 my @indexes;
135 185931         315156 foreach my $aref (@{$new->[1]}) {
  185931         446835  
136 68829         257172 my @tmp = map $_ + 1, @$aref;
137 68829         250901 push @indexes, [ @tmp ];
138             }
139 185931         341339 @{$new->[1]} = @indexes;
  185931         406015  
140              
141 185931         317589 my @flags;
142 185931         312357 foreach my $aref (@{$new->[3]}) {
  185931         410780  
143 191685         321720 my @tmp;
144 191685         410331 foreach my $value (@$aref) {
145 316380 100       790165 if (ref $value eq 'HASH') {
146 247551         412618 my %hash;
147 247551         800181 while (my ($key, $val) = each %$value) {
148 247551 100       1093079 $key++ if $key =~ /^\d+$/;
149 247551         934116 $hash{$key} = $val;
150             }
151 247551         907761 push @tmp, { %hash };
152             }
153             else {
154 68829         171126 push @tmp, $value + 1;
155             }
156             }
157 191685         547227 push @flags, [ @tmp ];
158             }
159 185931         320600 @{$new->[3]} = @flags;
  185931         770037  
160             }
161              
162             my %indexes = (
163             prefix => 0,
164 354930         646286 suffix => scalar keys %{$new->[0]},
  354930         1136850  
165             );
166              
167 354930         855698 my $i = $indexes{$type};
168              
169 354930         2385472 $new->[0]->{$i} = $self->{data}->__RE($element);
170              
171 354930 100       1160188 if (exists $data{$element}->{2}) {
172 236620         982211 $save->($type, $new->[1], [ $i ]);
173 236620         1341322 $save->($type, $new->[2], $self->{data}->__extended_checks($data{$element}->{2}));
174             }
175              
176 354930 100       665640 push @{$new->[3]}, exists $data{$element}->{3} ? [ { $i => [ $data{$element}->{3} ] } ] : [ $i ];
  354930         1700630  
177              
178 354930         697266 push @{$new->[4]}, $data{$element}->{4};
  354930         819897  
179 354930         628767 push @{$new->[5]}, $data{$element}->{5};
  354930         878003  
180              
181 354930         578632 foreach my $key (keys %{$data{$element}->{6}}) {
  354930         1159336  
182 354930         579490 push @{$new->[6]->{$key}}, @{$data{$element}->{6}->{$key}};
  354930         758469  
  354930         1042654  
183             }
184              
185 354930         1484976 push @expansions, [ $types, $new ];
186             }
187             }
188             }
189              
190 24126         193079 return @expansions;
191             }
192              
193             1;
194             __END__
195              
196             =head1 NAME
197              
198             DateTime::Format::Natural::Expand - Expand grammar at runtime
199              
200             =head1 SYNOPSIS
201              
202             Please see the DateTime::Format::Natural documentation.
203              
204             =head1 DESCRIPTION
205              
206             C<DateTime::Format::Natural::Expand> dynamically expands the grammar
207             at runtime in order to allow for additional time to be parsed.
208              
209             =head1 SEE ALSO
210              
211             L<DateTime::Format::Natural>
212              
213             =head1 AUTHOR
214              
215             Steven Schubiger <schubiger@cpan.org>
216              
217             =head1 LICENSE
218              
219             This program is free software; you may redistribute it and/or
220             modify it under the same terms as Perl itself.
221              
222             See L<http://dev.perl.org/licenses/>
223              
224             =cut