File Coverage

blib/lib/DateTime/Format/Builder/Parser/generic.pm
Criterion Covered Total %
statement 42 42 100.0
branch 23 30 76.6
condition 2 3 66.6
subroutine 8 8 100.0
pod 2 2 100.0
total 77 85 90.5


line stmt bran cond sub pod time code
1             package DateTime::Format::Builder::Parser::generic;
2              
3 24     24   144 use strict;
  24         50  
  24         902  
4 24     24   117 use warnings;
  24         49  
  24         943  
5              
6             our $VERSION = '0.83';
7              
8 24     24   146 use Carp;
  24         73  
  24         1421  
9 24         9111 use Params::Validate qw(
10             validate SCALAR CODEREF UNDEF
11 24     24   158 );
  24         58  
12              
13             sub new {
14 63     63 1 114 my $class = shift;
15 63         216 bless {@_}, $class;
16             }
17              
18             sub generic_parser {
19 63     63 1 118 my $class = shift;
20             my %args = validate(
21             @_,
22             {
23             (
24 63         149 map { $_ => { type => CODEREF, optional => 1 } }
  252         1517  
25             qw(
26             on_match on_fail preprocess postprocess
27             )
28             ),
29             label => { type => SCALAR | UNDEF, optional => 1 },
30             }
31             );
32 63         328 my $label = $args{label};
33              
34             my $callback
35 63 100 66     525 = ( exists $args{on_match} or exists $args{on_fail} ) ? 1 : undef;
36              
37             return sub {
38 84     84   365 my ( $self, $date, $p, @args ) = @_;
39 84 50       161 return unless defined $date;
40 84         119 my %p;
41 84 50       496 %p = %$p if $p; # Look! A Copy!
42              
43 84 50       257 my %param = (
    100          
44             self => $self,
45             ( defined $label ? ( label => $label ) : () ),
46             ( @args ? ( args => \@args ) : () ),
47             );
48              
49             # Preprocess - can modify $date and fill %p
50 84 100       194 if ( $args{preprocess} ) {
51             $date = $args{preprocess}
52 8         27 ->( input => $date, parsed => \%p, %param );
53             }
54              
55 84 50       540 my $rv = $class->do_match( $date, @args ) if $class->can('do_match');
56              
57             # Funky callback thing
58 84 100       292 if ($callback) {
59 6 100       21 my $type = defined $rv ? "on_match" : "on_fail";
60 6 50       34 $args{$type}->( input => $date, %param ) if $args{$type};
61             }
62 84 100       2718 return unless defined $rv;
63              
64 44         61 my $dt;
65 44 50       422 $dt = $class->post_match( $date, $rv, \%p )
66             if $class->can('post_match');
67              
68             # Allow post processing. Return undef if regarded as failure
69 44 100       115 if ( $args{postprocess} ) {
70 10         34 my $rv = $args{postprocess}->(
71             parsed => \%p,
72             input => $date,
73             post => $dt,
74             %param,
75             );
76 10 50       77 return unless $rv;
77             }
78              
79             # A successful match!
80 44 100       205 $dt = $class->make( $date, $dt, \%p ) if $class->can('make');
81 44         64333 return $dt;
82 63         596 };
83             }
84              
85             {
86 24     24   182 no strict 'refs';
  24         71  
  24         1754  
87             for (qw( valid_params params )) {
88             *$_ = *{"DateTime::Format::Builder::Parser::$_"};
89             }
90             }
91              
92             1;
93              
94             # ABSTRACT: Useful routines
95              
96             __END__
97              
98             =pod
99              
100             =encoding UTF-8
101              
102             =head1 NAME
103              
104             DateTime::Format::Builder::Parser::generic - Useful routines
105              
106             =head1 VERSION
107              
108             version 0.83
109              
110             =head1 METHODS
111              
112             =head2 Useful
113              
114             =head3 new
115              
116             Standard constructor. Returns a blessed hash; any arguments are placed in the
117             hash. This is useful for storing information between methods.
118              
119             =head3 generic_parser
120              
121             This is a method provided solely for the benefit of C<Parser>
122             implementations. It semi-neatly abstracts a lot of the work involved.
123              
124             Basically, it takes parameters matching the assorted callbacks from the parser
125             declarations and makes a coderef out of it all.
126              
127             Currently recognized callbacks are:
128              
129             =over 4
130              
131             =item * on_match
132              
133             =item * on_fail
134              
135             =item * preprocess
136              
137             =item * postprocess
138              
139             =back
140              
141             =head2 Methods for subclassing
142              
143             These are methods you should define when writing your own subclass.
144              
145             B<Note>: these methods do not exist in this class. There is no point trying to
146             call C<< $self->SUPER::do_match( ... ) >>.
147              
148             =head3 do_match
149              
150             C<do_match> is the first phase. Arguments are the date and @args. C<self>,
151             C<label>, C<args>. Return value must be defined if you match successfully.
152              
153             =head3 post_match
154              
155             C<post_match> is called after the appropriate callback out of
156             C<on_match>/C<on_fail> is done. It's passed the date, the return value from
157             C<do_match> and the parsing hash.
158              
159             Its return value is used as the C<post> argument to the C<postprocess>
160             callback, and as the second argument to C<make>.
161              
162             =head3 make
163              
164             C<make> takes the original input, the return value from C<post_match> and the
165             parsing hash and should return a C<DateTime> object or undefined.
166              
167             =head2 Delegations
168              
169             For use of C<Parser>, this module also delegates C<valid_params> and
170             C<params>. This is just convenience to save typing the following:
171              
172             DateTime::Format::Builder::Parser->valid_params(...)
173              
174             Instead we get to type:
175              
176             $self->valid_params(...);
177             __PACKAGE__->valid_params(...);
178              
179             =head1 WRITING A SUBCLASS
180              
181             Rather than attempt to explain how it all works, I think it's best if you take
182             a look at F<Regex.pm> and F<Strptime.pm> as examples and work from there.
183              
184             =head1 SEE ALSO
185              
186             C<datetime@perl.org> mailing list.
187              
188             http://datetime.perl.org/
189              
190             L<perl>, L<DateTime>, L<DateTime::Format::Builder>,
191             L<DateTime::Format::Builder::Parser>.
192              
193             =head1 SUPPORT
194              
195             Bugs may be submitted at L<https://github.com/houseabsolute/DateTime-Format-Builder/issues>.
196              
197             I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
198              
199             =head1 SOURCE
200              
201             The source code repository for DateTime-Format-Builder can be found at L<https://github.com/houseabsolute/DateTime-Format-Builder>.
202              
203             =head1 AUTHORS
204              
205             =over 4
206              
207             =item *
208              
209             Dave Rolsky <autarch@urth.org>
210              
211             =item *
212              
213             Iain Truskett <spoon@cpan.org>
214              
215             =back
216              
217             =head1 COPYRIGHT AND LICENSE
218              
219             This software is Copyright (c) 2020 by Dave Rolsky.
220              
221             This is free software, licensed under:
222              
223             The Artistic License 2.0 (GPL Compatible)
224              
225             The full text of the license can be found in the
226             F<LICENSE> file included with this distribution.
227              
228             =cut